diff --git a/.changeset/config.json b/.changeset/config.json
index 4f8345f46..bfd12d278 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -7,5 +7,5 @@
"access": "restricted",
"baseBranch": "master",
"updateInternalDependencies": "patch",
- "ignore": ["@0xsequence/wallet-primitives-cli", "docs", "web"]
+ "ignore": []
}
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 81c7b58d8..b5c68e55b 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -2,9 +2,8 @@
name: Bug report
about: Create a report to help us improve
title: ''
-labels: 'bug'
+labels: ''
assignees: ''
-
---
**Describe the bug**
@@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
+
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@@ -24,15 +24,17 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- - OS: [e.g. iOS]
- - Browser [e.g. chrome, safari]
- - Version [e.g. 22]
+
+- OS: [e.g. iOS]
+- Browser [e.g. chrome, safari]
+- Version [e.g. 22]
**Smartphone (please complete the following information):**
- - Device: [e.g. iPhone6]
- - OS: [e.g. iOS8.1]
- - Browser [e.g. stock browser, safari]
- - Version [e.g. 22]
+
+- Device: [e.g. iPhone6]
+- OS: [e.g. iOS8.1]
+- Browser [e.g. stock browser, safari]
+- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md
index 48d5f81fa..96a47352a 100644
--- a/.github/ISSUE_TEMPLATE/custom.md
+++ b/.github/ISSUE_TEMPLATE/custom.md
@@ -4,7 +4,4 @@ about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
-
---
-
-
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 36014cde5..2f28cead0 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -2,9 +2,8 @@
name: Feature request
about: Suggest an idea for this project
title: ''
-labels: 'enhancement'
+labels: ''
assignees: ''
-
---
**Is your feature request related to a problem? Please describe.**
diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml
new file mode 100644
index 000000000..974fcb999
--- /dev/null
+++ b/.github/workflows/nextjs.yml
@@ -0,0 +1,93 @@
+# Sample workflow for building and deploying a Next.js site to GitHub Pages
+#
+# To get started with Next.js see: https://nextjs.org/docs/getting-started
+#
+name: Deploy Next.js site to Pages
+
+on:
+ # Runs on pushes targeting the default branch
+ push:
+ branches: ["master"]
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
+# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ # Build job
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Detect package manager
+ id: detect-package-manager
+ run: |
+ if [ -f "${{ github.workspace }}/yarn.lock" ]; then
+ echo "manager=yarn" >> $GITHUB_OUTPUT
+ echo "command=install" >> $GITHUB_OUTPUT
+ echo "runner=yarn" >> $GITHUB_OUTPUT
+ exit 0
+ elif [ -f "${{ github.workspace }}/package.json" ]; then
+ echo "manager=npm" >> $GITHUB_OUTPUT
+ echo "command=ci" >> $GITHUB_OUTPUT
+ echo "runner=npx --no-install" >> $GITHUB_OUTPUT
+ exit 0
+ else
+ echo "Unable to determine package manager"
+ exit 1
+ fi
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: ${{ steps.detect-package-manager.outputs.manager }}
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+ with:
+ # Automatically inject basePath in your Next.js configuration file and disable
+ # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
+ #
+ # You may remove this line if you want to manage the configuration yourself.
+ static_site_generator: next
+ - name: Restore cache
+ uses: actions/cache@v4
+ with:
+ path: |
+ .next/cache
+ # Generate a new cache whenever packages or source files change.
+ key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
+ # If source files changed but packages didn't, rebuild from a prior cache.
+ restore-keys: |
+ ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
+ - name: Install dependencies
+ run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
+ - name: Build with Next.js
+ run: ${{ steps.detect-package-manager.outputs.runner }} next build
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./out
+
+ # Deployment job
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/on_pr_pnpm-format-label.yml b/.github/workflows/on_pr_pnpm-format-label.yml
index 83f23775a..84fb27cb3 100644
--- a/.github/workflows/on_pr_pnpm-format-label.yml
+++ b/.github/workflows/on_pr_pnpm-format-label.yml
@@ -1,9 +1,5 @@
name: pnpm-format-label
-permissions:
- contents: read
- issues: write
-
on:
pull_request:
types: [labeled]
diff --git a/.github/workflows/publish-dists.yml b/.github/workflows/publish-dists.yml
new file mode 100644
index 000000000..b8fd53b96
--- /dev/null
+++ b/.github/workflows/publish-dists.yml
@@ -0,0 +1,91 @@
+name: Publish Dists for Packages
+
+permissions:
+ contents: write
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - uses: ./.github/actions/install-dependencies
+
+ - name: Build package
+ run: pnpm run build
+
+ - name: Prepare dist branch
+ run: |
+ PACKAGES=("services/guard" "services/identity-instrument" "services/relayer" "wallet/core" "wallet/primitives" "wallet/wdk" "wallet/dapp-client")
+
+ for PACKAGE in "${PACKAGES[@]}"; do
+ BRANCH="dists/$PACKAGE"
+ PKG_DIR="packages/$PACKAGE"
+
+ echo "📦 Publishing $PACKAGE to $BRANCH"
+
+ mkdir -p /tmp/$PACKAGE
+ shopt -s dotglob
+ cp -r $PKG_DIR/* /tmp/$PACKAGE || true
+
+ cd /tmp/$PACKAGE
+ git init
+ git checkout -b $BRANCH
+
+ git config user.name "github-actions"
+ git config user.email "actions@github.com"
+
+ echo "🔧 Rewriting workspace: deps in package.json..."
+ node -e '
+ const fs = require("fs");
+ const path = require("path");
+ const pkgPath = path.resolve("package.json");
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
+ const repo = "github:0xsequence/sequence.js";
+
+ const versions = {
+ "@0xsequence/guard": `${repo}#dists/services/guard`,
+ "@0xsequence/identity-instrument": `${repo}#dists/services/identity-instrument`,
+ "@0xsequence/relayer": `${repo}#dists/services/relayer`,
+ "@0xsequence/wallet-core": `${repo}#dists/wallet/core`,
+ "@0xsequence/wallet-primitives": `${repo}#dists/wallet/primitives`,
+ "@0xsequence/wallet-wdk": `${repo}#dists/wallet/wdk`,
+ };
+
+ const rewrite = (deps = {}) => {
+ for (const k in deps) {
+ if (deps[k].startsWith("workspace:")) {
+ const version = versions[k];
+
+ if (!version) {
+ console.warn(`No version found for ${k}, skipping...`);
+ continue;
+ }
+
+ deps[k] = version;
+ console.log(`→ ${k} → ${deps[k]}`);
+ }
+ }
+ };
+
+ rewrite(pkg.dependencies);
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
+ '
+
+ git add .
+ git commit -m "Build: publish $PACKAGE dist"
+
+ git remote add origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
+ git push -f origin HEAD:$BRANCH
+
+ cd -
+ done
diff --git a/.github/workflows/web-sdk.yml b/.github/workflows/web-sdk.yml
new file mode 100644
index 000000000..e7253f1e3
--- /dev/null
+++ b/.github/workflows/web-sdk.yml
@@ -0,0 +1,137 @@
+name: Web-SDK
+on:
+ pull_request:
+ branches:
+ - master
+ - main
+ push:
+ branches:
+ - master
+ - main
+
+jobs:
+ master:
+ if: "! startsWith(github.event.head_commit.message, '[CI Skip]')"
+ runs-on: ubuntu-22.04
+ name: Build and Deploy
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - name: Web-SDK
+ uses: actions/setup-node@v3
+ with:
+ node-version: '18''20''22'
+ cache: 'yarn''npm''pnpm'
+ - name: Web SDK
+ id: Install the Web SDK dependencies
+ run: |
+ npm install @0xsequence/connect @0xsequence/hooks wagmi ethers viem 0xsequence @tanstack/react-query
+ # or
+ pnpm install @0xsequence/connect @0xsequence/hooks wagmi ethers viem 0xsequence @tanstack/react-query
+ # or
+ yarn add @0xsequence/connect @0xsequence/hooks wagmi ethers viem 0xsequence @tanstack/react-query
+
+ # === Deploy static pages ===
+ - name: Deploy to Cloudflare Pages
+ id: cloudflare_deployment
+ uses: cloudflare/pages-action@v1
+ with:
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+ projectName: 'w3o'
+ gitHubToken: ${{ secrets.GH_AUTOMATION_TOKEN }}
+ branch: 'main'
+ directory: './packages/demo/build'
+ wranglerVersion: '3'
+
+# Sample workflow for building and deploying a Next.js site to GitHub Pages
+#
+# To get started with Next.js see: https://nextjs.org/docs/getting-started
+#
+# Runs on pushes targeting the default branch
+ push:
+ branches: ["master"]
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
+# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ # Build job
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Detect package manager
+ id: detect-package-manager
+ run: |
+ if [ -f "${{ github.workspace }}/yarn.lock" ]; then
+ echo "manager=yarn" >> $GITHUB_OUTPUT
+ echo "command=install" >> $GITHUB_OUTPUT
+ echo "runner=yarn" >> $GITHUB_OUTPUT
+ exit 0
+ elif [ -f "${{ github.workspace }}/package.json" ]; then
+ echo "manager=npm" >> $GITHUB_OUTPUT
+ echo "command=ci" >> $GITHUB_OUTPUT
+ echo "runner=npx --no-install" >> $GITHUB_OUTPUT
+ exit 0
+ else
+ echo "Unable to determine package manager"
+ exit 1
+ fi
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+ cache: ${{ steps.detect-package-manager.outputs.manager }}
+ - name: Setup Pages
+ uses: actions/configure-pages@v5
+ with:
+ # Automatically inject basePath in your Next.js configuration file and disable
+ # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
+ #
+ # You may remove this line if you want to manage the configuration yourself.
+ static_site_generator: next
+ - name: Restore cache
+ uses: actions/cache@v4
+ with:
+ path: |
+ .next/cache
+ # Generate a new cache whenever packages or source files change.
+ key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
+ # If source files changed but packages didn't, rebuild from a prior cache.
+ restore-keys: |
+ ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
+ - name: Install dependencies
+ run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
+ - name: Build with Next.js
+ run: ${{ steps.detect-package-manager.outputs.runner }} next build
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./out
+
+ # Deployment job
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..6131d7399
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/signals-implicit-mode"]
+ path = lib/signals-implicit-mode
+ url = https://github.com/0xsequence/signals-implicit-mode
diff --git a/README.md b/README.md
index 93f43b66e..4c663ccf8 100644
--- a/README.md
+++ b/README.md
@@ -1,275 +1,39 @@
-
-
+## sequence.js v3 core libraries and SDK
-
-
-
-
-
-
-
-
-
-
-
-
- Reactive primitives for Ethereum apps (https://sequence.xyz/)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+**NOTE: please see [v2](https://github.com/0xsequence/sequence.js/tree/v2) branch for sequence.js 2.x.x**
---
-## Documentation
-
-For documentation and guides, visit [wagmi.sh](https://wagmi.sh).
-
-## Community
-
-For help, discussion about best practices, or any other conversation that would benefit from being searchable:
+Sequence v3 core libraries and [wallet-contracts-v3](https://github.com/0xsequence/wallet-contracts-v3) SDK.
-[Discuss Wagmi on GitHub](https://github.com/wevm/wagmi/discussions)
+## Packages
-For casual chit-chat with others using the framework:
+- `@0xsequence/wallet-primitives`: stateless low-level utilities specifically for interacting directly with sequence wallet's smart contracts
+- `@0xsequence/wallet-core`: higher level utilities for creating and using sequence wallets
+- `@0xsequence/wallet-wdk`: all-in-one wallet development kit for building a sequence wallet product
-[Join the Wagmi Discord](https://discord.gg/SghfWBKexF)
+## Development
-## Contributing
+### Getting Started
-Contributions to Wagmi are greatly appreciated! If you're interested in contributing to Wagmi, please read the [Contributing Guide](https://wagmi.sh/dev/contributing) **before submitting a pull request**.
+1. Install dependencies:
+ `pnpm install`
-## Sponsors
+2. Build all packages:
+ `pnpm build`
-If you find Wagmi useful or use it for work, please consider [sponsoring Wagmi](https://github.com/sponsors/wevm?metadata_campaign=gh_readme_support). Thank you 🙏
+### Development Workflow
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+- Run development mode across all packages:
+ `pnpm dev`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+- Run tests:
+ `pnpm test`
-[Sponsor Wagmi](https://github.com/sponsors/wevm?metadata_campaign=gh_readme_support_bottom)
+ > **Note:** Tests require [anvil](https://github.com/foundry-rs/foundry/tree/master/anvil) and [forge](https://github.com/foundry-rs/foundry) to be installed. You can run a local anvil instance using `pnpm run test:anvil`.
-
-
+- Linting and formatting is enforced via git hooks
-
-
-
-
-
-
-
+## License
+Apache-2.0
diff --git a/SECURITY.md b/SECURITY.md
index 6112730aa..c9a2fbd4c 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -16,4 +16,5 @@ currently being supported with security updates.
Use this section to tell people how to report a vulnerability.
-Tell them to email [your-security-email@example.com], and they can expect an initial response within 48 hours. We will provide regular updates on the status of the reported vulnerability.
+To report a vulnerability, please email us at [dev@wevm.dev](mailto:dev@wevm.dev). We aim to provide an initial response within 48 hours and will keep you updated on the status of the reported vulnerability.
+
diff --git a/corepack.tgz b/corepack.tgz
new file mode 100644
index 000000000..afa76b295
Binary files /dev/null and b/corepack.tgz differ
diff --git a/extras/docs/eslint.config.js b/extras/docs/eslint.config.js
index 0fbeffd97..3d2c2e9d4 100644
--- a/extras/docs/eslint.config.js
+++ b/extras/docs/eslint.config.js
@@ -1,9 +1,4 @@
import { nextJsConfig } from '@repo/eslint-config/next-js'
/** @type {import("eslint").Linter.Config} */
-export default [
- ...nextJsConfig,
- {
- ignores: ['next-env.d.ts'],
- },
-]
+export default nextJsConfig
diff --git a/extras/docs/next.config.js b/extras/docs/next.config.js
index 2963459c4..1d6147825 100644
--- a/extras/docs/next.config.js
+++ b/extras/docs/next.config.js
@@ -1,14 +1,4 @@
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url))
-const workspaceRoot = path.join(__dirname, '..', '..')
-
/** @type {import('next').NextConfig} */
-const nextConfig = {
- // Anchor output tracing to the monorepo root so Next.js doesn't pick up
- // sibling lockfiles and mis-detect the workspace boundary during lint/build.
- outputFileTracingRoot: workspaceRoot,
-}
+const nextConfig = {}
export default nextConfig
diff --git a/extras/docs/package.json b/extras/docs/package.json
index d5fedf082..d88f6aab1 100644
--- a/extras/docs/package.json
+++ b/extras/docs/package.json
@@ -7,23 +7,22 @@
"dev": "next dev --turbopack --port 3001",
"build": "next build",
"start": "next start",
- "lint": "eslint . --max-warnings 0",
+ "lint": "next lint --max-warnings 0",
"typecheck": "tsc --noEmit",
"clean": "rimraf .next"
},
"dependencies": {
- "@repo/ui": "workspace:^",
- "next": "^16.1.1",
- "react": "^19.2.3",
- "react-dom": "^19.2.3"
+ "@repo/ui": "workspace:*",
+ "next": "^15.4.7",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0"
},
"devDependencies": {
- "@repo/eslint-config": "workspace:^",
- "@repo/typescript-config": "workspace:^",
- "@types/node": "^25.0.2",
- "@types/react": "^19.2.7",
- "@types/react-dom": "^19.2.3",
- "eslint": "^9.39.2",
- "typescript": "^5.9.3"
+ "@repo/eslint-config": "workspace:*",
+ "@repo/typescript-config": "workspace:*",
+ "@types/node": "^20.17.57",
+ "@types/react": "18.3.1",
+ "@types/react-dom": "18.3.0",
+ "typescript": "5.5.4"
}
}
diff --git a/extras/web/eslint.config.js b/extras/web/eslint.config.js
index 0fbeffd97..3d2c2e9d4 100644
--- a/extras/web/eslint.config.js
+++ b/extras/web/eslint.config.js
@@ -1,9 +1,4 @@
import { nextJsConfig } from '@repo/eslint-config/next-js'
/** @type {import("eslint").Linter.Config} */
-export default [
- ...nextJsConfig,
- {
- ignores: ['next-env.d.ts'],
- },
-]
+export default nextJsConfig
diff --git a/extras/web/next.config.js b/extras/web/next.config.js
index 2963459c4..1d6147825 100644
--- a/extras/web/next.config.js
+++ b/extras/web/next.config.js
@@ -1,14 +1,4 @@
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
-
-const __dirname = path.dirname(fileURLToPath(import.meta.url))
-const workspaceRoot = path.join(__dirname, '..', '..')
-
/** @type {import('next').NextConfig} */
-const nextConfig = {
- // Anchor output tracing to the monorepo root so Next.js doesn't pick up
- // sibling lockfiles and mis-detect the workspace boundary during lint/build.
- outputFileTracingRoot: workspaceRoot,
-}
+const nextConfig = {}
export default nextConfig
diff --git a/extras/web/package.json b/extras/web/package.json
index 41ef60469..8a0ffdf21 100644
--- a/extras/web/package.json
+++ b/extras/web/package.json
@@ -7,23 +7,22 @@
"dev": "next dev --turbopack --port 3000",
"build": "next build",
"start": "next start",
- "lint": "eslint . --max-warnings 0",
+ "lint": "next lint --max-warnings 0",
"typecheck": "tsc --noEmit",
"clean": "rimraf .next"
},
"dependencies": {
- "@repo/ui": "workspace:^",
- "next": "^16.1.1",
- "react": "^19.2.3",
- "react-dom": "^19.2.3"
+ "@repo/ui": "workspace:*",
+ "next": "^15.4.7",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0"
},
"devDependencies": {
- "@repo/eslint-config": "workspace:^",
- "@repo/typescript-config": "workspace:^",
- "@types/node": "^25.0.2",
- "@types/react": "^19.2.7",
- "@types/react-dom": "^19.2.3",
- "eslint": "^9.39.2",
- "typescript": "^5.9.3"
+ "@repo/eslint-config": "workspace:*",
+ "@repo/typescript-config": "workspace:*",
+ "@types/node": "^20.17.57",
+ "@types/react": "18.3.1",
+ "@types/react-dom": "18.3.0",
+ "typescript": "5.5.4"
}
}
diff --git a/foundry.lock b/foundry.lock
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/foundry.lock
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/lefthook.yml b/lefthook.yml
index 7b9926c50..c66bba8e9 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -3,11 +3,6 @@ pre-commit:
prettier:
glob: '**/*.{js,jsx,ts,tsx,json,md,yml,yaml}'
run: pnpm prettier --write {staged_files} && git add {staged_files}
- syncpack:
- glob:
- - "package.json"
- - "packages/**/package.json"
- run: pnpm deps:lint
pre-push:
commands:
diff --git a/lib/signals-implicit-mode/.env.sample b/lib/signals-implicit-mode/.env.sample
new file mode 100644
index 000000000..6fc16b3cb
--- /dev/null
+++ b/lib/signals-implicit-mode/.env.sample
@@ -0,0 +1 @@
+PRIVATE_KEY=
diff --git a/lib/signals-implicit-mode/.github/workflows/test.yml b/lib/signals-implicit-mode/.github/workflows/test.yml
new file mode 100644
index 000000000..1be6707d7
--- /dev/null
+++ b/lib/signals-implicit-mode/.github/workflows/test.yml
@@ -0,0 +1,56 @@
+name: CI
+
+on:
+ push:
+ pull_request:
+ workflow_dispatch:
+
+env:
+ FOUNDRY_PROFILE: ci
+
+jobs:
+ check:
+ strategy:
+ fail-fast: true
+
+ name: Foundry project
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: false
+
+ - name: Use PAT
+ run: |
+ git config --global url."https://${{ secrets.SEQUENCE_V3_PAT }}@github.com/".insteadOf "https://github.com/"
+
+ - name: Download submodules
+ run: |
+ git submodule update --init --recursive
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+
+ - name: Show Forge version
+ run: |
+ forge --version
+
+ - name: Run Forge fmt
+ run: |
+ forge fmt --check
+ id: fmt
+
+ - name: Run Forge build
+ run: |
+ forge build --sizes
+ id: build
+
+ - name: Run Forge tests
+ run: |
+ forge test -vvv
+ id: test
+
+ - name: Run Coverage report
+ run: |
+ forge coverage --nmco "(script|test)"
+ id: coverage
diff --git a/lib/signals-implicit-mode/.gitmodules b/lib/signals-implicit-mode/.gitmodules
new file mode 100644
index 000000000..95a9dda98
--- /dev/null
+++ b/lib/signals-implicit-mode/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "lib/forge-std"]
+ path = lib/forge-std
+ url = https://github.com/foundry-rs/forge-std
+[submodule "lib/sequence-v3"]
+ path = lib/sequence-v3
+ url = https://github.com/0xsequence/sequence-v3
+[submodule "lib/erc2470-libs"]
+ path = lib/erc2470-libs
+ url = https://github.com/ScreamingHawk/erc2470-libs
diff --git a/lib/signals-implicit-mode/README.md b/lib/signals-implicit-mode/README.md
new file mode 100644
index 000000000..c89779b41
--- /dev/null
+++ b/lib/signals-implicit-mode/README.md
@@ -0,0 +1,84 @@
+# Signals Implicit Mode
+
+Libraries for managing support for [Sequence Ecosystem Wallet](https://github.com/0xsequence/sequence-v3)'s [implicit sessions](https://github.com/0xsequence/sequence-v3/blob/master/docs/SESSIONS.md).
+
+## Implicit Registry
+
+The `ImplicitProjectRegistry` is an ownerless, singleton contract that allows a single contract to define the accepted `redirectUrl`s for their project. Using the registry gives a single point for management of accepted `redirectUrl`s.
+
+Using the registry is also a quick way to authorize implicit access to contracts from other projects.
+
+See below _Support Implicit Sessions_ for information on how to integrate with the registry.
+
+### Register Your Project URLs
+
+Select your `Project ID`. The project ID is composed of two parts:
+
+- A 12-byte (24 hex characters) upper portion that you choose
+- Your address as the lower 20 bytes
+
+To claim your project ID, call the `claimProject(bytes12 projectIdUpper)` function. The contract will automatically combine your chosen upper portion with your address to create the full project ID.
+
+> [!TIP]
+> Consider claiming your project ID on every chain you wish to support. Claiming a project ID does not imply you must use it.
+
+As the project owner, you can:
+
+- Add supported redirect URLs by calling `addProjectUrl(bytes32 projectId, string memory projectUrl)`
+- Remove URLs using `removeProjectUrl(bytes32 projectId, string memory projectUrl)`
+- Transfer project ownership using `transferProject(bytes32 projectId, address newOwner)`
+
+Anyone can list all project URLs using `listProjectUrls(bytes32 projectId)`.
+
+Integrate your contracts with the registry using your project ID as described in the next section.
+
+## Support Implicit Sessions
+
+Import this library into your project using forge.
+
+```sh
+cd
+forge install https://github.com/0xsequence/signals-implicit-mode
+```
+
+Extend the provided abstract contract implementation.
+
+```solidity
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import {SignalsImplicitMode} from "signals-implicit-mode/helper/SignalsImplicitMode.sol";
+
+contract ImplicitSupportedContract is SignalsImplicitMode {
+ constructor(address registry, bytes32 projectId) {
+ _initializeSignalsImplicitMode(registry, projectId);
+ }
+}
+```
+
+Optionally, extend the validation by implementing the `_validateImplicitRequest` hook.
+
+## Run Tests
+
+```sh
+forge test
+```
+
+## Deploy Contracts
+
+> [!NOTE]
+> This will deploy the `ImplicitProjectRegistry`. Deployments use ERC-2470 for counter factual deployments and will deploy to `0x1dbaE3Df2A510768a36cE998396210Be12508d50`.
+
+> [!TIP]
+> The `ImplicitProjectRegistry` is ownerless and so you are free to use an implementation and claim any `projectId`. You do not need to deploy your own instance.
+
+Copy the `env.sample` file to `.env` and set the environment variables.
+
+```sh
+cp .env.sample .env
+# Edit .env
+```
+
+```sh
+forge script Deploy --rpc-url --broadcast
+```
diff --git a/lib/signals-implicit-mode/foundry.toml b/lib/signals-implicit-mode/foundry.toml
new file mode 100644
index 000000000..06e2d4bfe
--- /dev/null
+++ b/lib/signals-implicit-mode/foundry.toml
@@ -0,0 +1,22 @@
+[profile.default]
+src = "src"
+out = "out"
+libs = ["lib"]
+via-ir = false
+solc = "0.8.28"
+optimizer_runs = 200
+
+[fmt]
+# Explicitly define all formatting rules
+multiline_func_header = "params_first"
+single_line_statement_blocks = "multi"
+sort_imports = true
+contract_new_lines = true
+override_spacing = false
+line_length = 120
+tab_width = 2
+bracket_spacing = true
+int_types = "long"
+quote_style = "double"
+hex_underscore = "remove"
+wrap_comments = false
diff --git a/lib/signals-implicit-mode/lib/forge-std/.gitattributes b/lib/signals-implicit-mode/lib/forge-std/.gitattributes
new file mode 100644
index 000000000..27042d458
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/.gitattributes
@@ -0,0 +1 @@
+src/Vm.sol linguist-generated
diff --git a/lib/signals-implicit-mode/lib/forge-std/.github/CODEOWNERS b/lib/signals-implicit-mode/lib/forge-std/.github/CODEOWNERS
new file mode 100644
index 000000000..63b25bbbc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @danipopes @klkvr @mattsse @grandizzy @yash-atreya @zerosnacks
diff --git a/lib/signals-implicit-mode/lib/forge-std/.github/workflows/ci.yml b/lib/signals-implicit-mode/lib/forge-std/.github/workflows/ci.yml
new file mode 100644
index 000000000..8a4281ed0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/.github/workflows/ci.yml
@@ -0,0 +1,95 @@
+name: CI
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - master
+
+jobs:
+ build:
+ name: build +${{ matrix.toolchain }} ${{ matrix.flags }}
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ strategy:
+ fail-fast: false
+ matrix:
+ toolchain: [stable, nightly]
+ flags:
+ - ""
+ - --via-ir
+ - --use solc:0.8.17 --via-ir
+ - --use solc:0.8.17
+ - --use solc:0.8.0
+ - --use solc:0.7.6
+ - --use solc:0.7.0
+ - --use solc:0.6.2
+ - --use solc:0.6.12
+ steps:
+ - uses: actions/checkout@v4
+ - uses: foundry-rs/foundry-toolchain@v1
+ - run: forge --version
+ - run: |
+ case "${{ matrix.flags }}" in
+ *"solc:0.8.0"* | *"solc:0.7"* | *"solc:0.6"*)
+ forge build --skip test --skip Config --skip StdConfig --skip LibVariable --deny-warnings ${{ matrix.flags }}
+ ;;
+ *)
+ forge build --skip test --deny-warnings ${{ matrix.flags }}
+ ;;
+ esac
+ # via-ir compilation time checks.
+ - if: contains(matrix.flags, '--via-ir')
+ run: forge build --skip test --deny-warnings ${{ matrix.flags }} --contracts 'test/compilation/*'
+
+ test:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ strategy:
+ fail-fast: false
+ matrix:
+ toolchain: [stable, nightly]
+ steps:
+ - uses: actions/checkout@v4
+ - uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: ${{ matrix.toolchain }}
+ - run: forge --version
+ - run: |
+ if [ "${{ matrix.toolchain }}" = "stable" ]; then
+ forge test -vvv --no-match-path "test/Config.t.sol"
+ else
+ forge test -vvv
+ fi
+
+ fmt:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ steps:
+ - uses: actions/checkout@v4
+ - uses: foundry-rs/foundry-toolchain@v1
+ - run: forge --version
+ - run: forge fmt --check
+
+ typos:
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ steps:
+ - uses: actions/checkout@v4
+ - uses: crate-ci/typos@v1
+
+ ci-success:
+ runs-on: ubuntu-latest
+ if: always()
+ needs:
+ - build
+ - test
+ - fmt
+ - typos
+ timeout-minutes: 10
+ steps:
+ - name: Decide whether the needed jobs succeeded or failed
+ uses: re-actors/alls-green@release/v1
+ with:
+ jobs: ${{ toJSON(needs) }}
diff --git a/lib/signals-implicit-mode/lib/forge-std/.github/workflows/sync.yml b/lib/signals-implicit-mode/lib/forge-std/.github/workflows/sync.yml
new file mode 100644
index 000000000..9b170f0b7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/.github/workflows/sync.yml
@@ -0,0 +1,31 @@
+name: Sync Release Branch
+
+on:
+ release:
+ types:
+ - created
+
+jobs:
+ sync-release-branch:
+ runs-on: ubuntu-latest
+ if: startsWith(github.event.release.tag_name, 'v1')
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: v1
+
+ # The email is derived from the bots user id,
+ # found here: https://api.github.com/users/github-actions%5Bbot%5D
+ - name: Configure Git
+ run: |
+ git config user.name github-actions[bot]
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
+
+ - name: Sync Release Branch
+ run: |
+ git fetch --tags
+ git checkout v1
+ git reset --hard ${GITHUB_REF}
+ git push --force
diff --git a/lib/signals-implicit-mode/lib/forge-std/CONTRIBUTING.md b/lib/signals-implicit-mode/lib/forge-std/CONTRIBUTING.md
new file mode 100644
index 000000000..541e3d46f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/CONTRIBUTING.md
@@ -0,0 +1,193 @@
+## Contributing to Foundry
+
+Thanks for your interest in improving Foundry!
+
+There are multiple opportunities to contribute at any level. It doesn't matter if you are just getting started with Rust or are the most weathered expert, we can use your help.
+
+This document will help you get started. **Do not let the document intimidate you**.
+It should be considered as a guide to help you navigate the process.
+
+The [dev Telegram][dev-tg] is available for any concerns you may have that are not covered in this guide.
+
+### Code of Conduct
+
+The Foundry project adheres to the [Rust Code of Conduct][rust-coc]. This code of conduct describes the _minimum_ behavior expected from all contributors.
+
+Instances of violations of the Code of Conduct can be reported by contacting the team at [me@gakonst.com](mailto:me@gakonst.com).
+
+### Ways to contribute
+
+There are fundamentally four ways an individual can contribute:
+
+1. **By opening an issue:** For example, if you believe that you have uncovered a bug
+ in Foundry, creating a new issue in the issue tracker is the way to report it.
+2. **By adding context:** Providing additional context to existing issues,
+ such as screenshots and code snippets, which help resolve issues.
+3. **By resolving issues:** Typically this is done in the form of either
+ demonstrating that the issue reported is not a problem after all, or more often,
+ by opening a pull request that fixes the underlying problem, in a concrete and
+ reviewable manner.
+
+**Anybody can participate in any stage of contribution**. We urge you to participate in the discussion
+around bugs and participate in reviewing PRs.
+
+### Contributions Related to Spelling and Grammar
+
+At this time, we will not be accepting contributions that only fix spelling or grammatical errors in documentation, code or
+elsewhere.
+
+### Asking for help
+
+If you have reviewed existing documentation and still have questions, or you are having problems, you can get help in the following ways:
+
+- **Asking in the support Telegram:** The [Foundry Support Telegram][support-tg] is a fast and easy way to ask questions.
+- **Opening a discussion:** This repository comes with a discussions board where you can also ask for help. Click the "Discussions" tab at the top.
+
+As Foundry is still in heavy development, the documentation can be a bit scattered.
+The [Foundry Book][foundry-book] is our current best-effort attempt at keeping up-to-date information.
+
+### Submitting a bug report
+
+When filing a new bug report in the issue tracker, you will be presented with a basic form to fill out.
+
+If you believe that you have uncovered a bug, please fill out the form to the best of your ability. Do not worry if you cannot answer every detail; just fill in what you can. Contributors will ask follow-up questions if something is unclear.
+
+The most important pieces of information we need in a bug report are:
+
+- The Foundry version you are on (and that it is up to date)
+- The platform you are on (Windows, macOS, an M1 Mac or Linux)
+- Code snippets if this is happening in relation to testing or building code
+- Concrete steps to reproduce the bug
+
+In order to rule out the possibility of the bug being in your project, the code snippets should be as minimal
+as possible. It is better if you can reproduce the bug with a small snippet as opposed to an entire project!
+
+See [this guide][mcve] on how to create a minimal, complete, and verifiable example.
+
+### Submitting a feature request
+
+When adding a feature request in the issue tracker, you will be presented with a basic form to fill out.
+
+Please include as detailed of an explanation as possible of the feature you would like, adding additional context if necessary.
+
+If you have examples of other tools that have the feature you are requesting, please include them as well.
+
+### Resolving an issue
+
+Pull requests are the way concrete changes are made to the code, documentation, and dependencies of Foundry.
+
+Even minor pull requests, such as those fixing wording, are greatly appreciated. Before making a large change, it is usually
+a good idea to first open an issue describing the change to solicit feedback and guidance. This will increase
+the likelihood of the PR getting merged.
+
+Please make sure that the following commands pass if you have changed the code:
+
+```sh
+forge fmt --check
+forge test -vvv
+```
+
+To make sure your changes are compatible with all compiler version targets, run the following commands:
+
+```sh
+forge build --skip test --use solc:0.6.2
+forge build --skip test --use solc:0.6.12
+forge build --skip test --use solc:0.7.0
+forge build --skip test --use solc:0.7.6
+forge build --skip test --use solc:0.8.0
+```
+
+The CI will also ensure that the code is formatted correctly and that the tests are passing across all compiler version targets.
+
+#### Adding cheatcodes
+
+Please follow the guide outlined in the [cheatcodes](https://github.com/foundry-rs/foundry/blob/master/docs/dev/cheatcodes.md#adding-a-new-cheatcode) documentation of Foundry.
+
+When making modifications to the native cheatcodes or adding new ones, please make sure to run [`./scripts/vm.py`](./scripts/vm.py) to update the cheatcodes in the [`src/Vm.sol`](./src/Vm.sol) file.
+
+By default the script will automatically generate the cheatcodes from the [`cheatcodes.json`](https://raw.githubusercontent.com/foundry-rs/foundry/master/crates/cheatcodes/assets/cheatcodes.json) file but alternatively you can provide a path to a JSON file containing the Vm interface, as generated by Foundry, with the `--from` flag.
+
+```sh
+./scripts/vm.py --from path/to/cheatcodes.json
+```
+
+It is possible that the resulting [`src/Vm.sol`](./src/Vm.sol) file will have some changes that are not directly related to your changes, this is not a problem.
+
+#### Commits
+
+It is a recommended best practice to keep your changes as logically grouped as possible within individual commits. There is no limit to the number of commits any single pull request may have, and many contributors find it easier to review changes that are split across multiple commits.
+
+That said, if you have a number of commits that are "checkpoints" and don't represent a single logical change, please squash those together.
+
+#### Opening the pull request
+
+From within GitHub, opening a new pull request will present you with a template that should be filled out. Please try your best at filling out the details, but feel free to skip parts if you're not sure what to put.
+
+#### Discuss and update
+
+You will probably get feedback or requests for changes to your pull request.
+This is a big part of the submission process, so don't be discouraged! Some contributors may sign off on the pull request right away, others may have more detailed comments or feedback.
+This is a necessary part of the process in order to evaluate whether the changes are correct and necessary.
+
+**Any community member can review a PR, so you might get conflicting feedback**.
+Keep an eye out for comments from code owners to provide guidance on conflicting feedback.
+
+#### Reviewing pull requests
+
+**Any Foundry community member is welcome to review any pull request**.
+
+All contributors who choose to review and provide feedback on pull requests have a responsibility to both the project and individual making the contribution. Reviews and feedback must be helpful, insightful, and geared towards improving the contribution as opposed to simply blocking it. If there are reasons why you feel the PR should not be merged, explain what those are. Do not expect to be able to block a PR from advancing simply because you say "no" without giving an explanation. Be open to having your mind changed. Be open to working _with_ the contributor to make the pull request better.
+
+Reviews that are dismissive or disrespectful of the contributor or any other reviewers are strictly counter to the Code of Conduct.
+
+When reviewing a pull request, the primary goals are for the codebase to improve and for the person submitting the request to succeed. **Even if a pull request is not merged, the submitter should come away from the experience feeling like their effort was not unappreciated**. Every PR from a new contributor is an opportunity to grow the community.
+
+##### Review a bit at a time
+
+Do not overwhelm new contributors.
+
+It is tempting to micro-optimize and make everything about relative performance, perfect grammar, or exact style matches. Do not succumb to that temptation..
+
+Focus first on the most significant aspects of the change:
+
+1. Does this change make sense for Foundry?
+2. Does this change make Foundry better, even if only incrementally?
+3. Are there clear bugs or larger scale issues that need attending?
+4. Are the commit messages readable and correct? If it contains a breaking change, is it clear enough?
+
+Note that only **incremental** improvement is needed to land a PR. This means that the PR does not need to be perfect, only better than the status quo. Follow-up PRs may be opened to continue iterating.
+
+When changes are necessary, _request_ them, do not _demand_ them, and **do not assume that the submitter already knows how to add a test or run a benchmark**.
+
+Specific performance optimization techniques, coding styles and conventions change over time. The first impression you give to a new contributor never does.
+
+Nits (requests for small changes that are not essential) are fine, but try to avoid stalling the pull request. Most nits can typically be fixed by the Foundry maintainers merging the pull request, but they can also be an opportunity for the contributor to learn a bit more about the project.
+
+It is always good to clearly indicate nits when you comment, e.g.: `Nit: change foo() to bar(). But this is not blocking`.
+
+If your comments were addressed but were not folded after new commits, or if they proved to be mistaken, please, [hide them][hiding-a-comment] with the appropriate reason to keep the conversation flow concise and relevant.
+
+##### Be aware of the person behind the code
+
+Be aware that _how_ you communicate requests and reviews in your feedback can have a significant impact on the success of the pull request. Yes, we may merge a particular change that makes Foundry better, but the individual might just not want to have anything to do with Foundry ever again. The goal is not just having good code.
+
+##### Abandoned or stale pull requests
+
+If a pull request appears to be abandoned or stalled, it is polite to first check with the contributor to see if they intend to continue the work before checking if they would mind if you took it over (especially if it just has nits left). When doing so, it is courteous to give the original contributor credit for the work they started, either by preserving their name and e-mail address in the commit log, or by using the `Author: ` or `Co-authored-by: ` metadata tag in the commits.
+
+_Adapted from the [ethers-rs contributing guide](https://github.com/gakonst/ethers-rs/blob/master/CONTRIBUTING.md)_.
+
+### Releasing
+
+Releases are automatically done by the release workflow when a tag is pushed, however, these steps still need to be taken:
+
+1. Ensure that the versions in the relevant `Cargo.toml` files are up-to-date.
+2. Update documentation links
+3. Perform a final audit for breaking changes.
+
+[rust-coc]: https://github.com/rust-lang/rust/blob/master/CODE_OF_CONDUCT.md
+[dev-tg]: https://t.me/foundry_rs
+[foundry-book]: https://github.com/foundry-rs/foundry-book
+[support-tg]: https://t.me/foundry_support
+[mcve]: https://stackoverflow.com/help/mcve
+[hiding-a-comment]: https://help.github.com/articles/managing-disruptive-comments/#hiding-a-comment
diff --git a/lib/signals-implicit-mode/lib/forge-std/LICENSE-APACHE b/lib/signals-implicit-mode/lib/forge-std/LICENSE-APACHE
new file mode 100644
index 000000000..cf01a499f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/LICENSE-APACHE
@@ -0,0 +1,203 @@
+Copyright Contributors to Forge Standard Library
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/lib/signals-implicit-mode/lib/forge-std/LICENSE-MIT b/lib/signals-implicit-mode/lib/forge-std/LICENSE-MIT
new file mode 100644
index 000000000..28f98304a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright Contributors to Forge Standard Library
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.R
diff --git a/lib/signals-implicit-mode/lib/forge-std/README.md b/lib/signals-implicit-mode/lib/forge-std/README.md
new file mode 100644
index 000000000..91b16f015
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/README.md
@@ -0,0 +1,268 @@
+# Forge Standard Library • [](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml)
+
+Forge Standard Library is a collection of helpful contracts and libraries for use with [Forge and Foundry](https://github.com/foundry-rs/foundry). It leverages Forge's cheatcodes to make writing tests easier and faster, while improving the UX of cheatcodes.
+
+**Learn how to use Forge-Std with the [📖 Foundry Book (Forge-Std Guide)](https://getfoundry.sh/reference/forge-std/overview/).**
+
+## Install
+
+```bash
+forge install foundry-rs/forge-std
+```
+
+## Contracts
+
+### stdError
+
+This is a helper contract for errors and reverts. In Forge, this contract is particularly helpful for the `expectRevert` cheatcode, as it provides all compiler built-in errors.
+
+See the contract itself for all error codes.
+
+#### Example usage
+
+```solidity
+
+import "forge-std/Test.sol";
+
+contract TestContract is Test {
+ ErrorsTest test;
+
+ function setUp() public {
+ test = new ErrorsTest();
+ }
+
+ function testExpectArithmetic() public {
+ vm.expectRevert(stdError.arithmeticError);
+ test.arithmeticError(10);
+ }
+}
+
+contract ErrorsTest {
+ function arithmeticError(uint256 a) public {
+ a = a - 100;
+ }
+}
+```
+
+### stdStorage
+
+This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can _always_ find and write the storage slot(s) associated with a particular variable without knowing the storage layout. The one _major_ caveat to this is while a slot can be found for packed storage variables, we can't write to that variable safely. If a user tries to write to a packed slot, the execution throws an error, unless it is uninitialized (`bytes32(0)`).
+
+This works by recording all `SLOAD`s and `SSTORE`s during a function call. If there is a single slot read or written to, it immediately returns the slot. Otherwise, behind the scenes, we iterate through and check each one (assuming the user passed in a `depth` parameter). If the variable is a struct, you can pass in a `depth` parameter which is basically the field depth.
+
+I.e.:
+
+```solidity
+struct T {
+ // depth 0
+ uint256 a;
+ // depth 1
+ uint256 b;
+}
+```
+
+#### Example usage
+
+```solidity
+import "forge-std/Test.sol";
+
+contract TestContract is Test {
+ using stdStorage for StdStorage;
+
+ Storage test;
+
+ function setUp() public {
+ test = new Storage();
+ }
+
+ function testFindExists() public {
+ // Lets say we want to find the slot for the public
+ // variable `exists`. We just pass in the function selector
+ // to the `find` command
+ uint256 slot = stdstore.target(address(test)).sig("exists()").find();
+ assertEq(slot, 0);
+ }
+
+ function testWriteExists() public {
+ // Lets say we want to write to the slot for the public
+ // variable `exists`. We just pass in the function selector
+ // to the `checked_write` command
+ stdstore.target(address(test)).sig("exists()").checked_write(100);
+ assertEq(test.exists(), 100);
+ }
+
+ // It supports arbitrary storage layouts, like assembly based storage locations
+ function testFindHidden() public {
+ // `hidden` is a random hash of a bytes, iteration through slots would
+ // not find it. Our mechanism does
+ // Also, you can use the selector instead of a string
+ uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find();
+ assertEq(slot, uint256(keccak256("my.random.var")));
+ }
+
+ // If targeting a mapping, you have to pass in the keys necessary to perform the find
+ // i.e.:
+ function testFindMapping() public {
+ uint256 slot = stdstore
+ .target(address(test))
+ .sig(test.map_addr.selector)
+ .with_key(address(this))
+ .find();
+ // in the `Storage` constructor, we wrote that this address' value was 1 in the map
+ // so when we load the slot, we expect it to be 1
+ assertEq(uint(vm.load(address(test), bytes32(slot))), 1);
+ }
+
+ // If the target is a struct, you can specify the field depth:
+ function testFindStruct() public {
+ // NOTE: see the depth parameter - 0 means 0th field, 1 means 1st field, etc.
+ uint256 slot_for_a_field = stdstore
+ .target(address(test))
+ .sig(test.basicStruct.selector)
+ .depth(0)
+ .find();
+
+ uint256 slot_for_b_field = stdstore
+ .target(address(test))
+ .sig(test.basicStruct.selector)
+ .depth(1)
+ .find();
+
+ assertEq(uint(vm.load(address(test), bytes32(slot_for_a_field))), 1);
+ assertEq(uint(vm.load(address(test), bytes32(slot_for_b_field))), 2);
+ }
+}
+
+// A complex storage contract
+contract Storage {
+ struct UnpackedStruct {
+ uint256 a;
+ uint256 b;
+ }
+
+ constructor() {
+ map_addr[msg.sender] = 1;
+ }
+
+ uint256 public exists = 1;
+ mapping(address => uint256) public map_addr;
+ // mapping(address => Packed) public map_packed;
+ mapping(address => UnpackedStruct) public map_struct;
+ mapping(address => mapping(address => uint256)) public deep_map;
+ mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
+ UnpackedStruct public basicStruct = UnpackedStruct({
+ a: 1,
+ b: 2
+ });
+
+ function hidden() public view returns (bytes32 t) {
+ // an extremely hidden storage slot
+ bytes32 slot = keccak256("my.random.var");
+ assembly {
+ t := sload(slot)
+ }
+ }
+}
+```
+
+### stdCheats
+
+This is a wrapper over miscellaneous cheatcodes that need wrappers to be more dev friendly. Currently there are only functions related to `prank`. In general, users may expect ETH to be put into an address on `prank`, but this is not the case for safety reasons. Explicitly this `hoax` function should only be used for addresses that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you.
+
+#### Example usage:
+
+```solidity
+
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "forge-std/Test.sol";
+
+// Inherit the stdCheats
+contract StdCheatsTest is Test {
+ Bar test;
+ function setUp() public {
+ test = new Bar();
+ }
+
+ function testHoax() public {
+ // we call `hoax`, which gives the target address
+ // eth and then calls `prank`
+ hoax(address(1337));
+ test.bar{value: 100}(address(1337));
+
+ // overloaded to allow you to specify how much eth to
+ // initialize the address with
+ hoax(address(1337), 1);
+ test.bar{value: 1}(address(1337));
+ }
+
+ function testStartHoax() public {
+ // we call `startHoax`, which gives the target address
+ // eth and then calls `startPrank`
+ //
+ // it is also overloaded so that you can specify an eth amount
+ startHoax(address(1337));
+ test.bar{value: 100}(address(1337));
+ test.bar{value: 100}(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+}
+
+contract Bar {
+ function bar(address expectedSender) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ }
+}
+```
+
+### Std Assertions
+
+Contains various assertions.
+
+### `console.log`
+
+Usage follows the same format as [Hardhat](https://hardhat.org/hardhat-network/reference/#console-log).
+It's recommended to use `console2.sol` as shown below, as this will show the decoded logs in Forge traces.
+
+```solidity
+// import it indirectly via Test.sol
+import "forge-std/Test.sol";
+// or directly import it
+import "forge-std/console2.sol";
+...
+console2.log(someValue);
+```
+
+If you need compatibility with Hardhat, you must use the standard `console.sol` instead.
+Due to a bug in `console.sol`, logs that use `uint256` or `int256` types will not be properly decoded in Forge traces.
+
+```solidity
+// import it indirectly via Test.sol
+import "forge-std/Test.sol";
+// or directly import it
+import "forge-std/console.sol";
+...
+console.log(someValue);
+```
+
+## Contributing
+
+See our [contributing guidelines](./CONTRIBUTING.md).
+
+## Getting Help
+
+First, see if the answer to your question can be found in [book](https://book.getfoundry.sh).
+
+If the answer is not there:
+
+- Join the [support Telegram](https://t.me/foundry_support) to get help, or
+- Open a [discussion](https://github.com/foundry-rs/foundry/discussions/new/choose) with your question, or
+- Open an issue with [the bug](https://github.com/foundry-rs/foundry/issues/new/choose)
+
+If you want to contribute, or follow along with contributor discussion, you can use our [main telegram](https://t.me/foundry_rs) to chat with us about the development of Foundry!
+
+## License
+
+Forge Standard Library is offered under either [MIT](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE) license.
diff --git a/lib/signals-implicit-mode/lib/forge-std/RELEASE_CHECKLIST.md b/lib/signals-implicit-mode/lib/forge-std/RELEASE_CHECKLIST.md
new file mode 100644
index 000000000..4611de4dc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/RELEASE_CHECKLIST.md
@@ -0,0 +1,12 @@
+# Release checklist
+
+This checklist is meant to be used as a guide for the `forge-std` release process.
+
+## Steps
+
+- [ ] Update the version number in `package.json`
+- [ ] Open and merge a PR with the version bump
+- [ ] Tag the merged commit with the version number: `git tag v`
+- [ ] Push the tag to the repository: `git push --tags`
+- [ ] Create a new GitHub release with the automatically generated changelog and with the name set to `v`
+- [ ] Add `## Featured Changes` section to the top of the release notes
diff --git a/lib/signals-implicit-mode/lib/forge-std/foundry.toml b/lib/signals-implicit-mode/lib/forge-std/foundry.toml
new file mode 100644
index 000000000..b68bd546c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/foundry.toml
@@ -0,0 +1,27 @@
+[profile.default]
+fs_permissions = [{ access = "read-write", path = "./" }]
+optimizer = true
+optimizer_runs = 200
+
+# A list of solidity error codes to ignore.
+# 3860 = init-code-size
+ignored_error_codes = [3860]
+
+[rpc_endpoints]
+# The RPC URLs are modified versions of the default for testing initialization.
+mainnet = "https://eth.merkle.io" # Different API key.
+optimism_sepolia = "https://sepolia.optimism.io/" # Adds a trailing slash.
+arbitrum_one_sepolia = "https://sepolia-rollup.arbitrum.io/rpc/" # Adds a trailing slash.
+needs_undefined_env_var = "${UNDEFINED_RPC_URL_PLACEHOLDER}"
+
+[fmt]
+# These are all the `forge fmt` defaults.
+line_length = 120
+tab_width = 4
+bracket_spacing = false
+int_types = 'long'
+multiline_func_header = 'attributes_first'
+quote_style = 'double'
+number_underscore = 'preserve'
+single_line_statement_blocks = 'preserve'
+ignore = ["src/console.sol", "src/console2.sol"]
diff --git a/lib/signals-implicit-mode/lib/forge-std/package.json b/lib/signals-implicit-mode/lib/forge-std/package.json
new file mode 100644
index 000000000..74e5e6679
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "forge-std",
+ "version": "1.10.0",
+ "description": "Forge Standard Library is a collection of helpful contracts and libraries for use with Forge and Foundry.",
+ "homepage": "https://book.getfoundry.sh/forge/forge-std",
+ "bugs": "https://github.com/foundry-rs/forge-std/issues",
+ "license": "(Apache-2.0 OR MIT)",
+ "author": "Contributors to Forge Standard Library",
+ "files": [
+ "src/**/*"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/foundry-rs/forge-std.git"
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/scripts/vm.py b/lib/signals-implicit-mode/lib/forge-std/scripts/vm.py
new file mode 100644
index 000000000..3cd047d36
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/scripts/vm.py
@@ -0,0 +1,646 @@
+#!/usr/bin/env python3
+
+import argparse
+import copy
+import json
+import re
+import subprocess
+from enum import Enum as PyEnum
+from pathlib import Path
+from typing import Callable
+from urllib import request
+
+VoidFn = Callable[[], None]
+
+CHEATCODES_JSON_URL = "https://raw.githubusercontent.com/foundry-rs/foundry/master/crates/cheatcodes/assets/cheatcodes.json"
+OUT_PATH = "src/Vm.sol"
+
+VM_SAFE_DOC = """\
+/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
+/// result in Script simulations differing from on-chain execution. It is recommended to only use
+/// these cheats in scripts.
+"""
+
+VM_DOC = """\
+/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
+/// in tests, but it is not recommended to use these cheats in scripts.
+"""
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Generate Vm.sol based on the cheatcodes json created by Foundry")
+ parser.add_argument(
+ "--from",
+ metavar="PATH",
+ dest="path",
+ required=False,
+ help="path to a json file containing the Vm interface, as generated by Foundry")
+ args = parser.parse_args()
+ json_str = request.urlopen(CHEATCODES_JSON_URL).read().decode("utf-8") if args.path is None else Path(args.path).read_text()
+ contract = Cheatcodes.from_json(json_str)
+
+ ccs = contract.cheatcodes
+ ccs = list(filter(lambda cc: cc.status not in ["experimental", "internal"], ccs))
+ ccs.sort(key=lambda cc: cc.func.id)
+
+ safe = list(filter(lambda cc: cc.safety == "safe", ccs))
+ safe.sort(key=CmpCheatcode)
+ unsafe = list(filter(lambda cc: cc.safety == "unsafe", ccs))
+ unsafe.sort(key=CmpCheatcode)
+ assert len(safe) + len(unsafe) == len(ccs)
+
+ prefix_with_group_headers(safe)
+ prefix_with_group_headers(unsafe)
+
+ out = ""
+
+ out += "// Automatically @generated by scripts/vm.py. Do not modify manually.\n\n"
+
+ pp = CheatcodesPrinter(
+ spdx_identifier="MIT OR Apache-2.0",
+ solidity_requirement=">=0.6.2 <0.9.0",
+ abicoder_pragma=True,
+ )
+ pp.p_prelude()
+ pp.prelude = False
+ out += pp.finish()
+
+ out += "\n\n"
+ out += VM_SAFE_DOC
+ vm_safe = Cheatcodes(
+ # TODO: Custom errors were introduced in 0.8.4
+ errors=[], # contract.errors
+ events=contract.events,
+ enums=contract.enums,
+ structs=contract.structs,
+ cheatcodes=safe,
+ )
+ pp.p_contract(vm_safe, "VmSafe")
+ out += pp.finish()
+
+ out += "\n\n"
+ out += VM_DOC
+ vm_unsafe = Cheatcodes(
+ errors=[],
+ events=[],
+ enums=[],
+ structs=[],
+ cheatcodes=unsafe,
+ )
+ pp.p_contract(vm_unsafe, "Vm", "VmSafe")
+ out += pp.finish()
+
+ # Compatibility with <0.8.0
+ def memory_to_calldata(m: re.Match) -> str:
+ return " calldata " + m.group(1)
+
+ out = re.sub(r" memory (.*returns)", memory_to_calldata, out)
+
+ with open(OUT_PATH, "w") as f:
+ f.write(out)
+
+ forge_fmt = ["forge", "fmt", OUT_PATH]
+ res = subprocess.run(forge_fmt)
+ assert res.returncode == 0, f"command failed: {forge_fmt}"
+
+ print(f"Wrote to {OUT_PATH}")
+
+
+class CmpCheatcode:
+ cheatcode: "Cheatcode"
+
+ def __init__(self, cheatcode: "Cheatcode"):
+ self.cheatcode = cheatcode
+
+ def __lt__(self, other: "CmpCheatcode") -> bool:
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) < 0
+
+ def __eq__(self, other: "CmpCheatcode") -> bool:
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) == 0
+
+ def __gt__(self, other: "CmpCheatcode") -> bool:
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) > 0
+
+
+def cmp_cheatcode(a: "Cheatcode", b: "Cheatcode") -> int:
+ if a.group != b.group:
+ return -1 if a.group < b.group else 1
+ if a.status != b.status:
+ return -1 if a.status < b.status else 1
+ if a.safety != b.safety:
+ return -1 if a.safety < b.safety else 1
+ if a.func.id != b.func.id:
+ return -1 if a.func.id < b.func.id else 1
+ return 0
+
+
+# HACK: A way to add group header comments without having to modify printer code
+def prefix_with_group_headers(cheats: list["Cheatcode"]):
+ s = set()
+ for i, cheat in enumerate(cheats):
+ if cheat.group in s:
+ continue
+
+ s.add(cheat.group)
+
+ c = copy.deepcopy(cheat)
+ c.func.description = ""
+ c.func.declaration = f"// ======== {group(c.group)} ========"
+ cheats.insert(i, c)
+ return cheats
+
+
+def group(s: str) -> str:
+ if s == "evm":
+ return "EVM"
+ if s == "json":
+ return "JSON"
+ return s[0].upper() + s[1:]
+
+
+class Visibility(PyEnum):
+ EXTERNAL: str = "external"
+ PUBLIC: str = "public"
+ INTERNAL: str = "internal"
+ PRIVATE: str = "private"
+
+ def __str__(self):
+ return self.value
+
+
+class Mutability(PyEnum):
+ PURE: str = "pure"
+ VIEW: str = "view"
+ NONE: str = ""
+
+ def __str__(self):
+ return self.value
+
+
+class Function:
+ id: str
+ description: str
+ declaration: str
+ visibility: Visibility
+ mutability: Mutability
+ signature: str
+ selector: str
+ selector_bytes: bytes
+
+ def __init__(
+ self,
+ id: str,
+ description: str,
+ declaration: str,
+ visibility: Visibility,
+ mutability: Mutability,
+ signature: str,
+ selector: str,
+ selector_bytes: bytes,
+ ):
+ self.id = id
+ self.description = description
+ self.declaration = declaration
+ self.visibility = visibility
+ self.mutability = mutability
+ self.signature = signature
+ self.selector = selector
+ self.selector_bytes = selector_bytes
+
+ @staticmethod
+ def from_dict(d: dict) -> "Function":
+ return Function(
+ d["id"],
+ d["description"],
+ d["declaration"],
+ Visibility(d["visibility"]),
+ Mutability(d["mutability"]),
+ d["signature"],
+ d["selector"],
+ bytes(d["selectorBytes"]),
+ )
+
+
+class Cheatcode:
+ func: Function
+ group: str
+ status: str
+ safety: str
+
+ def __init__(self, func: Function, group: str, status: str, safety: str):
+ self.func = func
+ self.group = group
+ self.status = status
+ self.safety = safety
+
+ @staticmethod
+ def from_dict(d: dict) -> "Cheatcode":
+ return Cheatcode(
+ Function.from_dict(d["func"]),
+ str(d["group"]),
+ str(d["status"]),
+ str(d["safety"]),
+ )
+
+
+class Error:
+ name: str
+ description: str
+ declaration: str
+
+ def __init__(self, name: str, description: str, declaration: str):
+ self.name = name
+ self.description = description
+ self.declaration = declaration
+
+ @staticmethod
+ def from_dict(d: dict) -> "Error":
+ return Error(**d)
+
+
+class Event:
+ name: str
+ description: str
+ declaration: str
+
+ def __init__(self, name: str, description: str, declaration: str):
+ self.name = name
+ self.description = description
+ self.declaration = declaration
+
+ @staticmethod
+ def from_dict(d: dict) -> "Event":
+ return Event(**d)
+
+
+class EnumVariant:
+ name: str
+ description: str
+
+ def __init__(self, name: str, description: str):
+ self.name = name
+ self.description = description
+
+
+class Enum:
+ name: str
+ description: str
+ variants: list[EnumVariant]
+
+ def __init__(self, name: str, description: str, variants: list[EnumVariant]):
+ self.name = name
+ self.description = description
+ self.variants = variants
+
+ @staticmethod
+ def from_dict(d: dict) -> "Enum":
+ return Enum(
+ d["name"],
+ d["description"],
+ list(map(lambda v: EnumVariant(**v), d["variants"])),
+ )
+
+
+class StructField:
+ name: str
+ ty: str
+ description: str
+
+ def __init__(self, name: str, ty: str, description: str):
+ self.name = name
+ self.ty = ty
+ self.description = description
+
+
+class Struct:
+ name: str
+ description: str
+ fields: list[StructField]
+
+ def __init__(self, name: str, description: str, fields: list[StructField]):
+ self.name = name
+ self.description = description
+ self.fields = fields
+
+ @staticmethod
+ def from_dict(d: dict) -> "Struct":
+ return Struct(
+ d["name"],
+ d["description"],
+ list(map(lambda f: StructField(**f), d["fields"])),
+ )
+
+
+class Cheatcodes:
+ errors: list[Error]
+ events: list[Event]
+ enums: list[Enum]
+ structs: list[Struct]
+ cheatcodes: list[Cheatcode]
+
+ def __init__(
+ self,
+ errors: list[Error],
+ events: list[Event],
+ enums: list[Enum],
+ structs: list[Struct],
+ cheatcodes: list[Cheatcode],
+ ):
+ self.errors = errors
+ self.events = events
+ self.enums = enums
+ self.structs = structs
+ self.cheatcodes = cheatcodes
+
+ @staticmethod
+ def from_dict(d: dict) -> "Cheatcodes":
+ return Cheatcodes(
+ errors=[Error.from_dict(e) for e in d["errors"]],
+ events=[Event.from_dict(e) for e in d["events"]],
+ enums=[Enum.from_dict(e) for e in d["enums"]],
+ structs=[Struct.from_dict(e) for e in d["structs"]],
+ cheatcodes=[Cheatcode.from_dict(e) for e in d["cheatcodes"]],
+ )
+
+ @staticmethod
+ def from_json(s) -> "Cheatcodes":
+ return Cheatcodes.from_dict(json.loads(s))
+
+ @staticmethod
+ def from_json_file(file_path: str) -> "Cheatcodes":
+ with open(file_path, "r") as f:
+ return Cheatcodes.from_dict(json.load(f))
+
+
+class Item(PyEnum):
+ ERROR: str = "error"
+ EVENT: str = "event"
+ ENUM: str = "enum"
+ STRUCT: str = "struct"
+ FUNCTION: str = "function"
+
+
+class ItemOrder:
+ _list: list[Item]
+
+ def __init__(self, list: list[Item]) -> None:
+ assert len(list) <= len(Item), "list must not contain more items than Item"
+ assert len(list) == len(set(list)), "list must not contain duplicates"
+ self._list = list
+ pass
+
+ def get_list(self) -> list[Item]:
+ return self._list
+
+ @staticmethod
+ def default() -> "ItemOrder":
+ return ItemOrder(
+ [
+ Item.ERROR,
+ Item.EVENT,
+ Item.ENUM,
+ Item.STRUCT,
+ Item.FUNCTION,
+ ]
+ )
+
+
+class CheatcodesPrinter:
+ buffer: str
+
+ prelude: bool
+ spdx_identifier: str
+ solidity_requirement: str
+ abicoder_v2: bool
+
+ block_doc_style: bool
+
+ indent_level: int
+ _indent_str: str
+
+ nl_str: str
+
+ items_order: ItemOrder
+
+ def __init__(
+ self,
+ buffer: str = "",
+ prelude: bool = True,
+ spdx_identifier: str = "UNLICENSED",
+ solidity_requirement: str = "",
+ abicoder_pragma: bool = False,
+ block_doc_style: bool = False,
+ indent_level: int = 0,
+ indent_with: int | str = 4,
+ nl_str: str = "\n",
+ items_order: ItemOrder = ItemOrder.default(),
+ ):
+ self.prelude = prelude
+ self.spdx_identifier = spdx_identifier
+ self.solidity_requirement = solidity_requirement
+ self.abicoder_v2 = abicoder_pragma
+ self.block_doc_style = block_doc_style
+ self.buffer = buffer
+ self.indent_level = indent_level
+ self.nl_str = nl_str
+
+ if isinstance(indent_with, int):
+ assert indent_with >= 0
+ self._indent_str = " " * indent_with
+ elif isinstance(indent_with, str):
+ self._indent_str = indent_with
+ else:
+ assert False, "indent_with must be int or str"
+
+ self.items_order = items_order
+
+ def finish(self) -> str:
+ ret = self.buffer.rstrip()
+ self.buffer = ""
+ return ret
+
+ def p_contract(self, contract: Cheatcodes, name: str, inherits: str = ""):
+ if self.prelude:
+ self.p_prelude(contract)
+
+ self._p_str("interface ")
+ name = name.strip()
+ if name != "":
+ self._p_str(name)
+ self._p_str(" ")
+ if inherits != "":
+ self._p_str("is ")
+ self._p_str(inherits)
+ self._p_str(" ")
+ self._p_str("{")
+ self._p_nl()
+ self._with_indent(lambda: self._p_items(contract))
+ self._p_str("}")
+ self._p_nl()
+
+ def _p_items(self, contract: Cheatcodes):
+ for item in self.items_order.get_list():
+ if item == Item.ERROR:
+ self.p_errors(contract.errors)
+ elif item == Item.EVENT:
+ self.p_events(contract.events)
+ elif item == Item.ENUM:
+ self.p_enums(contract.enums)
+ elif item == Item.STRUCT:
+ self.p_structs(contract.structs)
+ elif item == Item.FUNCTION:
+ self.p_functions(contract.cheatcodes)
+ else:
+ assert False, f"unknown item {item}"
+
+ def p_prelude(self, contract: Cheatcodes | None = None):
+ self._p_str(f"// SPDX-License-Identifier: {self.spdx_identifier}")
+ self._p_nl()
+
+ if self.solidity_requirement != "":
+ req = self.solidity_requirement
+ elif contract and len(contract.errors) > 0:
+ req = ">=0.8.4 <0.9.0"
+ else:
+ req = ">=0.6.0 <0.9.0"
+ self._p_str(f"pragma solidity {req};")
+ self._p_nl()
+
+ if self.abicoder_v2:
+ self._p_str("pragma experimental ABIEncoderV2;")
+ self._p_nl()
+
+ self._p_nl()
+
+ def p_errors(self, errors: list[Error]):
+ for error in errors:
+ self._p_line(lambda: self.p_error(error))
+
+ def p_error(self, error: Error):
+ self._p_comment(error.description, doc=True)
+ self._p_line(lambda: self._p_str(error.declaration))
+
+ def p_events(self, events: list[Event]):
+ for event in events:
+ self._p_line(lambda: self.p_event(event))
+
+ def p_event(self, event: Event):
+ self._p_comment(event.description, doc=True)
+ self._p_line(lambda: self._p_str(event.declaration))
+
+ def p_enums(self, enums: list[Enum]):
+ for enum in enums:
+ self._p_line(lambda: self.p_enum(enum))
+
+ def p_enum(self, enum: Enum):
+ self._p_comment(enum.description, doc=True)
+ self._p_line(lambda: self._p_str(f"enum {enum.name} {{"))
+ self._with_indent(lambda: self.p_enum_variants(enum.variants))
+ self._p_line(lambda: self._p_str("}"))
+
+ def p_enum_variants(self, variants: list[EnumVariant]):
+ for i, variant in enumerate(variants):
+ self._p_indent()
+ self._p_comment(variant.description)
+
+ self._p_indent()
+ self._p_str(variant.name)
+ if i < len(variants) - 1:
+ self._p_str(",")
+ self._p_nl()
+
+ def p_structs(self, structs: list[Struct]):
+ for struct in structs:
+ self._p_line(lambda: self.p_struct(struct))
+
+ def p_struct(self, struct: Struct):
+ self._p_comment(struct.description, doc=True)
+ self._p_line(lambda: self._p_str(f"struct {struct.name} {{"))
+ self._with_indent(lambda: self.p_struct_fields(struct.fields))
+ self._p_line(lambda: self._p_str("}"))
+
+ def p_struct_fields(self, fields: list[StructField]):
+ for field in fields:
+ self._p_line(lambda: self.p_struct_field(field))
+
+ def p_struct_field(self, field: StructField):
+ self._p_comment(field.description)
+ self._p_indented(lambda: self._p_str(f"{field.ty} {field.name};"))
+
+ def p_functions(self, cheatcodes: list[Cheatcode]):
+ for cheatcode in cheatcodes:
+ self._p_line(lambda: self.p_function(cheatcode.func))
+
+ def p_function(self, func: Function):
+ self._p_comment(func.description, doc=True)
+ self._p_line(lambda: self._p_str(func.declaration))
+
+ def _p_comment(self, s: str, doc: bool = False):
+ s = s.strip()
+ if s == "":
+ return
+
+ s = map(lambda line: line.lstrip(), s.split("\n"))
+ if self.block_doc_style:
+ self._p_str("/*")
+ if doc:
+ self._p_str("*")
+ self._p_nl()
+ for line in s:
+ self._p_indent()
+ self._p_str(" ")
+ if doc:
+ self._p_str("* ")
+ self._p_str(line)
+ self._p_nl()
+ self._p_indent()
+ self._p_str(" */")
+ self._p_nl()
+ else:
+ first_line = True
+ for line in s:
+ if not first_line:
+ self._p_indent()
+ first_line = False
+
+ if doc:
+ self._p_str("/// ")
+ else:
+ self._p_str("// ")
+ self._p_str(line)
+ self._p_nl()
+
+ def _with_indent(self, f: VoidFn):
+ self._inc_indent()
+ f()
+ self._dec_indent()
+
+ def _p_line(self, f: VoidFn):
+ self._p_indent()
+ f()
+ self._p_nl()
+
+ def _p_indented(self, f: VoidFn):
+ self._p_indent()
+ f()
+
+ def _p_indent(self):
+ for _ in range(self.indent_level):
+ self._p_str(self._indent_str)
+
+ def _p_nl(self):
+ self._p_str(self.nl_str)
+
+ def _p_str(self, txt: str):
+ self.buffer += txt
+
+ def _inc_indent(self):
+ self.indent_level += 1
+
+ def _dec_indent(self):
+ self.indent_level -= 1
+
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/Base.sol b/lib/signals-implicit-mode/lib/forge-std/src/Base.sol
new file mode 100644
index 000000000..52a508210
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/Base.sol
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {StdStorage} from "./StdStorage.sol";
+import {Vm, VmSafe} from "./Vm.sol";
+
+abstract contract CommonBase {
+ /// @dev Cheat code address.
+ /// Calculated as `address(uint160(uint256(keccak256("hevm cheat code"))))`.
+ address internal constant VM_ADDRESS = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D;
+
+ /// @dev console.sol and console2.sol work by executing a staticcall to this address.
+ /// Calculated as `address(uint160(uint88(bytes11("console.log"))))`.
+ address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
+
+ /// @dev Used when deploying with create2.
+ /// Taken from https://github.com/Arachnid/deterministic-deployment-proxy.
+ address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+
+ /// @dev The default address for tx.origin and msg.sender.
+ /// Calculated as `address(uint160(uint256(keccak256("foundry default caller"))))`.
+ address internal constant DEFAULT_SENDER = 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
+
+ /// @dev The address of the first contract `CREATE`d by a running test contract.
+ /// When running tests, each test contract is `CREATE`d by `DEFAULT_SENDER` with nonce 1.
+ /// Calculated as `VM.computeCreateAddress(VM.computeCreateAddress(DEFAULT_SENDER, 1), 1)`.
+ address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
+
+ /// @dev Deterministic deployment address of the Multicall3 contract.
+ /// Taken from https://www.multicall3.com.
+ address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
+
+ /// @dev The order of the secp256k1 curve.
+ uint256 internal constant SECP256K1_ORDER =
+ 115792089237316195423570985008687907852837564279074904382605163141518161494337;
+
+ uint256 internal constant UINT256_MAX =
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ Vm internal constant vm = Vm(VM_ADDRESS);
+ StdStorage internal stdstore;
+}
+
+abstract contract TestBase is CommonBase {}
+
+abstract contract ScriptBase is CommonBase {
+ VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/Config.sol b/lib/signals-implicit-mode/lib/forge-std/src/Config.sol
new file mode 100644
index 000000000..1c63c8721
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/Config.sol
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+import {console} from "./console.sol";
+import {StdConfig} from "./StdConfig.sol";
+import {CommonBase} from "./Base.sol";
+
+/// @notice Boilerplate to streamline the setup of multi-chain environments.
+abstract contract Config is CommonBase {
+ // -- STORAGE (CONFIG + CHAINS + FORKS) ------------------------------------
+
+ /// @dev Contract instance holding the data from the TOML config file.
+ StdConfig internal config;
+
+ /// @dev Array of chain IDs for which forks have been created.
+ uint256[] internal chainIds;
+
+ /// @dev A mapping from a chain ID to its initialized fork ID.
+ mapping(uint256 => uint256) internal forkOf;
+
+ // -- HELPER FUNCTIONS -----------------------------------------------------
+
+ /// @notice Loads configuration from a file.
+ ///
+ /// @dev This function instantiates a `Config` contract, caching all its config variables.
+ ///
+ /// @param filePath: the path to the TOML configuration file.
+ /// @param writeToFile: whether updates are written back to the TOML file.
+ function _loadConfig(string memory filePath, bool writeToFile) internal {
+ console.log("----------");
+ console.log(string.concat("Loading config from '", filePath, "'"));
+ config = new StdConfig(filePath, writeToFile);
+ vm.makePersistent(address(config));
+ console.log("Config successfully loaded");
+ console.log("----------");
+ }
+
+ /// @notice Loads configuration from a file and creates forks for each specified chain.
+ ///
+ /// @dev This function instantiates a `Config` contract, caching all its config variables,
+ /// reads the configured chain ids, and iterates through them to create a fork for each one.
+ /// It also creates a map `forkOf[chainId] -> forkId` to easily switch between forks.
+ ///
+ /// @param filePath: the path to the TOML configuration file.
+ /// @param writeToFile: whether updates are written back to the TOML file.
+ function _loadConfigAndForks(string memory filePath, bool writeToFile) internal {
+ _loadConfig(filePath, writeToFile);
+
+ console.log("Setting up forks for the configured chains...");
+ uint256[] memory chains = config.getChainIds();
+ for (uint256 i = 0; i < chains.length; i++) {
+ uint256 chainId = chains[i];
+ uint256 forkId = vm.createFork(config.getRpcUrl(chainId));
+ forkOf[chainId] = forkId;
+ chainIds.push(chainId);
+ }
+ console.log("Forks successfully created");
+ console.log("----------");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/LibVariable.sol b/lib/signals-implicit-mode/lib/forge-std/src/LibVariable.sol
new file mode 100644
index 000000000..c46b15328
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/LibVariable.sol
@@ -0,0 +1,477 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+// Enable globally.
+using LibVariable for Variable global;
+
+struct Variable {
+ Type ty;
+ bytes data;
+}
+
+struct Type {
+ TypeKind kind;
+ bool isArray;
+}
+
+enum TypeKind {
+ None,
+ Bool,
+ Address,
+ Bytes32,
+ Uint256,
+ Int256,
+ String,
+ Bytes
+}
+
+/// @notice Library for type-safe coercion of the `Variable` struct to concrete types.
+///
+/// @dev Ensures that when a `Variable` is cast to a concrete Solidity type, the operation is safe and the
+/// underlying type matches what is expected.
+/// Provides functions to check types, convert them to strings, and coerce `Variable` instances into
+/// both single values and arrays of various types.
+///
+/// Usage example:
+/// ```solidity
+/// import {LibVariable} from "./LibVariable.sol";
+///
+/// contract MyContract {
+/// using LibVariable for Variable;
+/// StdConfig config; // Assume 'config' is an instance of `StdConfig` and has already been loaded.
+///
+/// function readValues() public {
+/// // Retrieve a 'uint256' value from the config.
+/// uint256 myNumber = config.get("important_number").toUint256();
+///
+/// // Would revert with `TypeMismatch` as 'important_number' isn't a `uint256` in the config file.
+/// // string memory notANumber = config.get("important_number").toString();
+///
+/// // Retrieve a address array from the config.
+/// string[] memory admins = config.get("whitelisted_admins").toAddressArray();
+/// }
+/// }
+/// ```
+library LibVariable {
+ error NotInitialized();
+ error TypeMismatch(string expected, string actual);
+ error UnsafeCast(string message);
+
+ // -- TYPE HELPERS ----------------------------------------------------
+
+ /// @notice Compares two Type instances for equality.
+ function isEqual(Type memory self, Type memory other) internal pure returns (bool) {
+ return self.kind == other.kind && self.isArray == other.isArray;
+ }
+
+ /// @notice Compares two Type instances for equality. Reverts if they are not equal.
+ function assertEq(Type memory self, Type memory other) internal pure {
+ if (!isEqual(self, other)) {
+ revert TypeMismatch(toString(other), toString(self));
+ }
+ }
+
+ /// @notice Converts a Type struct to its full string representation (i.e. "uint256[]").
+ function toString(Type memory self) internal pure returns (string memory) {
+ string memory tyStr = toString(self.kind);
+ if (!self.isArray || self.kind == TypeKind.None) {
+ return tyStr;
+ } else {
+ return string.concat(tyStr, "[]");
+ }
+ }
+
+ /// @dev Converts a `TypeKind` enum to its base string representation.
+ function toString(TypeKind self) internal pure returns (string memory) {
+ if (self == TypeKind.Bool) return "bool";
+ if (self == TypeKind.Address) return "address";
+ if (self == TypeKind.Bytes32) return "bytes32";
+ if (self == TypeKind.Uint256) return "uint256";
+ if (self == TypeKind.Int256) return "int256";
+ if (self == TypeKind.String) return "string";
+ if (self == TypeKind.Bytes) return "bytes";
+ return "none";
+ }
+
+ /// @dev Converts a `TypeKind` enum to its base string representation.
+ function toTomlKey(TypeKind self) internal pure returns (string memory) {
+ if (self == TypeKind.Bool) return "bool";
+ if (self == TypeKind.Address) return "address";
+ if (self == TypeKind.Bytes32) return "bytes32";
+ if (self == TypeKind.Uint256) return "uint";
+ if (self == TypeKind.Int256) return "int";
+ if (self == TypeKind.String) return "string";
+ if (self == TypeKind.Bytes) return "bytes";
+ return "none";
+ }
+
+ // -- VARIABLE HELPERS ----------------------------------------------------
+
+ /// @dev Checks if a `Variable` has been initialized and matches the expected type reverting if not.
+ modifier check(Variable memory self, Type memory expected) {
+ assertExists(self);
+ assertEq(self.ty, expected);
+ _;
+ }
+
+ /// @dev Checks if a `Variable` has been initialized, reverting if not.
+ function assertExists(Variable memory self) public pure {
+ if (self.ty.kind == TypeKind.None) {
+ revert NotInitialized();
+ }
+ }
+
+ // -- VARIABLE COERCION FUNCTIONS (SINGLE VALUES) --------------------------
+
+ /// @notice Coerces a `Variable` to a `bool` value.
+ function toBool(Variable memory self) internal pure check(self, Type(TypeKind.Bool, false)) returns (bool) {
+ return abi.decode(self.data, (bool));
+ }
+
+ /// @notice Coerces a `Variable` to an `address` value.
+ function toAddress(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Address, false))
+ returns (address)
+ {
+ return abi.decode(self.data, (address));
+ }
+
+ /// @notice Coerces a `Variable` to a `bytes32` value.
+ function toBytes32(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Bytes32, false))
+ returns (bytes32)
+ {
+ return abi.decode(self.data, (bytes32));
+ }
+
+ /// @notice Coerces a `Variable` to a `uint256` value.
+ function toUint256(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Uint256, false))
+ returns (uint256)
+ {
+ return abi.decode(self.data, (uint256));
+ }
+
+ /// @notice Coerces a `Variable` to a `uint128` value, checking for overflow.
+ function toUint128(Variable memory self) internal pure returns (uint128) {
+ uint256 value = self.toUint256();
+ if (value > type(uint128).max) {
+ revert UnsafeCast("value does not fit in 'uint128'");
+ }
+ return uint128(value);
+ }
+
+ /// @notice Coerces a `Variable` to a `uint64` value, checking for overflow.
+ function toUint64(Variable memory self) internal pure returns (uint64) {
+ uint256 value = self.toUint256();
+ if (value > type(uint64).max) {
+ revert UnsafeCast("value does not fit in 'uint64'");
+ }
+ return uint64(value);
+ }
+
+ /// @notice Coerces a `Variable` to a `uint32` value, checking for overflow.
+ function toUint32(Variable memory self) internal pure returns (uint32) {
+ uint256 value = self.toUint256();
+ if (value > type(uint32).max) {
+ revert UnsafeCast("value does not fit in 'uint32'");
+ }
+ return uint32(value);
+ }
+
+ /// @notice Coerces a `Variable` to a `uint16` value, checking for overflow.
+ function toUint16(Variable memory self) internal pure returns (uint16) {
+ uint256 value = self.toUint256();
+ if (value > type(uint16).max) {
+ revert UnsafeCast("value does not fit in 'uint16'");
+ }
+ return uint16(value);
+ }
+
+ /// @notice Coerces a `Variable` to a `uint8` value, checking for overflow.
+ function toUint8(Variable memory self) internal pure returns (uint8) {
+ uint256 value = self.toUint256();
+ if (value > type(uint8).max) {
+ revert UnsafeCast("value does not fit in 'uint8'");
+ }
+ return uint8(value);
+ }
+
+ /// @notice Coerces a `Variable` to an `int256` value.
+ function toInt256(Variable memory self) internal pure check(self, Type(TypeKind.Int256, false)) returns (int256) {
+ return abi.decode(self.data, (int256));
+ }
+
+ /// @notice Coerces a `Variable` to an `int128` value, checking for overflow/underflow.
+ function toInt128(Variable memory self) internal pure returns (int128) {
+ int256 value = self.toInt256();
+ if (value > type(int128).max || value < type(int128).min) {
+ revert UnsafeCast("value does not fit in 'int128'");
+ }
+ return int128(value);
+ }
+
+ /// @notice Coerces a `Variable` to an `int64` value, checking for overflow/underflow.
+ function toInt64(Variable memory self) internal pure returns (int64) {
+ int256 value = self.toInt256();
+ if (value > type(int64).max || value < type(int64).min) {
+ revert UnsafeCast("value does not fit in 'int64'");
+ }
+ return int64(value);
+ }
+
+ /// @notice Coerces a `Variable` to an `int32` value, checking for overflow/underflow.
+ function toInt32(Variable memory self) internal pure returns (int32) {
+ int256 value = self.toInt256();
+ if (value > type(int32).max || value < type(int32).min) {
+ revert UnsafeCast("value does not fit in 'int32'");
+ }
+ return int32(value);
+ }
+
+ /// @notice Coerces a `Variable` to an `int16` value, checking for overflow/underflow.
+ function toInt16(Variable memory self) internal pure returns (int16) {
+ int256 value = self.toInt256();
+ if (value > type(int16).max || value < type(int16).min) {
+ revert UnsafeCast("value does not fit in 'int16'");
+ }
+ return int16(value);
+ }
+
+ /// @notice Coerces a `Variable` to an `int8` value, checking for overflow/underflow.
+ function toInt8(Variable memory self) internal pure returns (int8) {
+ int256 value = self.toInt256();
+ if (value > type(int8).max || value < type(int8).min) {
+ revert UnsafeCast("value does not fit in 'int8'");
+ }
+ return int8(value);
+ }
+
+ /// @notice Coerces a `Variable` to a `string` value.
+ function toString(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.String, false))
+ returns (string memory)
+ {
+ return abi.decode(self.data, (string));
+ }
+
+ /// @notice Coerces a `Variable` to a `bytes` value.
+ function toBytes(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Bytes, false))
+ returns (bytes memory)
+ {
+ return abi.decode(self.data, (bytes));
+ }
+
+ // -- VARIABLE COERCION FUNCTIONS (ARRAYS) ---------------------------------
+
+ /// @notice Coerces a `Variable` to a `bool` array.
+ function toBoolArray(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Bool, true))
+ returns (bool[] memory)
+ {
+ return abi.decode(self.data, (bool[]));
+ }
+
+ /// @notice Coerces a `Variable` to an `address` array.
+ function toAddressArray(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Address, true))
+ returns (address[] memory)
+ {
+ return abi.decode(self.data, (address[]));
+ }
+
+ /// @notice Coerces a `Variable` to a `bytes32` array.
+ function toBytes32Array(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Bytes32, true))
+ returns (bytes32[] memory)
+ {
+ return abi.decode(self.data, (bytes32[]));
+ }
+
+ /// @notice Coerces a `Variable` to a `uint256` array.
+ function toUint256Array(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Uint256, true))
+ returns (uint256[] memory)
+ {
+ return abi.decode(self.data, (uint256[]));
+ }
+
+ /// @notice Coerces a `Variable` to a `uint128` array, checking for overflow.
+ function toUint128Array(Variable memory self) internal pure returns (uint128[] memory) {
+ uint256[] memory values = self.toUint256Array();
+ uint128[] memory result = new uint128[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(uint128).max) {
+ revert UnsafeCast("value in array does not fit in 'uint128'");
+ }
+ result[i] = uint128(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `uint64` array, checking for overflow.
+ function toUint64Array(Variable memory self) internal pure returns (uint64[] memory) {
+ uint256[] memory values = self.toUint256Array();
+ uint64[] memory result = new uint64[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(uint64).max) {
+ revert UnsafeCast("value in array does not fit in 'uint64'");
+ }
+ result[i] = uint64(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `uint32` array, checking for overflow.
+ function toUint32Array(Variable memory self) internal pure returns (uint32[] memory) {
+ uint256[] memory values = self.toUint256Array();
+ uint32[] memory result = new uint32[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(uint32).max) {
+ revert UnsafeCast("value in array does not fit in 'uint32'");
+ }
+ result[i] = uint32(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `uint16` array, checking for overflow.
+ function toUint16Array(Variable memory self) internal pure returns (uint16[] memory) {
+ uint256[] memory values = self.toUint256Array();
+ uint16[] memory result = new uint16[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(uint16).max) {
+ revert UnsafeCast("value in array does not fit in 'uint16'");
+ }
+ result[i] = uint16(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `uint8` array, checking for overflow.
+ function toUint8Array(Variable memory self) internal pure returns (uint8[] memory) {
+ uint256[] memory values = self.toUint256Array();
+ uint8[] memory result = new uint8[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(uint8).max) {
+ revert UnsafeCast("value in array does not fit in 'uint8'");
+ }
+ result[i] = uint8(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to an `int256` array.
+ function toInt256Array(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Int256, true))
+ returns (int256[] memory)
+ {
+ return abi.decode(self.data, (int256[]));
+ }
+
+ /// @notice Coerces a `Variable` to a `int128` array, checking for overflow/underflow.
+ function toInt128Array(Variable memory self) internal pure returns (int128[] memory) {
+ int256[] memory values = self.toInt256Array();
+ int128[] memory result = new int128[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(int128).max || values[i] < type(int128).min) {
+ revert UnsafeCast("value in array does not fit in 'int128'");
+ }
+ result[i] = int128(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `int64` array, checking for overflow/underflow.
+ function toInt64Array(Variable memory self) internal pure returns (int64[] memory) {
+ int256[] memory values = self.toInt256Array();
+ int64[] memory result = new int64[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(int64).max || values[i] < type(int64).min) {
+ revert UnsafeCast("value in array does not fit in 'int64'");
+ }
+ result[i] = int64(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `int32` array, checking for overflow/underflow.
+ function toInt32Array(Variable memory self) internal pure returns (int32[] memory) {
+ int256[] memory values = self.toInt256Array();
+ int32[] memory result = new int32[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(int32).max || values[i] < type(int32).min) {
+ revert UnsafeCast("value in array does not fit in 'int32'");
+ }
+ result[i] = int32(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `int16` array, checking for overflow/underflow.
+ function toInt16Array(Variable memory self) internal pure returns (int16[] memory) {
+ int256[] memory values = self.toInt256Array();
+ int16[] memory result = new int16[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(int16).max || values[i] < type(int16).min) {
+ revert UnsafeCast("value in array does not fit in 'int16'");
+ }
+ result[i] = int16(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `int8` array, checking for overflow/underflow.
+ function toInt8Array(Variable memory self) internal pure returns (int8[] memory) {
+ int256[] memory values = self.toInt256Array();
+ int8[] memory result = new int8[](values.length);
+ for (uint256 i = 0; i < values.length; i++) {
+ if (values[i] > type(int8).max || values[i] < type(int8).min) {
+ revert UnsafeCast("value in array does not fit in 'int8'");
+ }
+ result[i] = int8(values[i]);
+ }
+ return result;
+ }
+
+ /// @notice Coerces a `Variable` to a `string` array.
+ function toStringArray(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.String, true))
+ returns (string[] memory)
+ {
+ return abi.decode(self.data, (string[]));
+ }
+
+ /// @notice Coerces a `Variable` to a `bytes` array.
+ function toBytesArray(Variable memory self)
+ internal
+ pure
+ check(self, Type(TypeKind.Bytes, true))
+ returns (bytes[] memory)
+ {
+ return abi.decode(self.data, (bytes[]));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/Script.sol b/lib/signals-implicit-mode/lib/forge-std/src/Script.sol
new file mode 100644
index 000000000..a2e2aa1cd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/Script.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+// 💬 ABOUT
+// Forge Std's default Script.
+
+// 🧩 MODULES
+import {console} from "./console.sol";
+import {console2} from "./console2.sol";
+import {safeconsole} from "./safeconsole.sol";
+import {StdChains} from "./StdChains.sol";
+import {StdCheatsSafe} from "./StdCheats.sol";
+import {StdConstants} from "./StdConstants.sol";
+import {stdJson} from "./StdJson.sol";
+import {stdMath} from "./StdMath.sol";
+import {StdStorage, stdStorageSafe} from "./StdStorage.sol";
+import {StdStyle} from "./StdStyle.sol";
+import {StdUtils} from "./StdUtils.sol";
+import {VmSafe} from "./Vm.sol";
+
+// 📦 BOILERPLATE
+import {ScriptBase} from "./Base.sol";
+
+// ⭐️ SCRIPT
+abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils {
+ // Note: IS_SCRIPT() must return true.
+ bool public IS_SCRIPT = true;
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdAssertions.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdAssertions.sol
new file mode 100644
index 000000000..4248170da
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdAssertions.sol
@@ -0,0 +1,764 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import {Vm} from "./Vm.sol";
+
+abstract contract StdAssertions {
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ event log(string);
+ event logs(bytes);
+
+ event log_address(address);
+ event log_bytes32(bytes32);
+ event log_int(int256);
+ event log_uint(uint256);
+ event log_bytes(bytes);
+ event log_string(string);
+
+ event log_named_address(string key, address val);
+ event log_named_bytes32(string key, bytes32 val);
+ event log_named_decimal_int(string key, int256 val, uint256 decimals);
+ event log_named_decimal_uint(string key, uint256 val, uint256 decimals);
+ event log_named_int(string key, int256 val);
+ event log_named_uint(string key, uint256 val);
+ event log_named_bytes(string key, bytes val);
+ event log_named_string(string key, string val);
+
+ event log_array(uint256[] val);
+ event log_array(int256[] val);
+ event log_array(address[] val);
+ event log_named_array(string key, uint256[] val);
+ event log_named_array(string key, int256[] val);
+ event log_named_array(string key, address[] val);
+
+ bytes32 private constant FAILED_SLOT = bytes32("failed");
+
+ bool private _failed;
+
+ function failed() public view returns (bool) {
+ if (_failed) {
+ return true;
+ } else {
+ return vm.load(address(vm), FAILED_SLOT) != bytes32(0);
+ }
+ }
+
+ function fail() internal virtual {
+ vm.store(address(vm), FAILED_SLOT, bytes32(uint256(1)));
+ _failed = true;
+ }
+
+ function fail(string memory message) internal virtual {
+ fail();
+ vm.assertTrue(false, message);
+ }
+
+ function assertTrue(bool data) internal pure virtual {
+ if (!data) {
+ vm.assertTrue(data);
+ }
+ }
+
+ function assertTrue(bool data, string memory err) internal pure virtual {
+ if (!data) {
+ vm.assertTrue(data, err);
+ }
+ }
+
+ function assertFalse(bool data) internal pure virtual {
+ if (data) {
+ vm.assertFalse(data);
+ }
+ }
+
+ function assertFalse(bool data, string memory err) internal pure virtual {
+ if (data) {
+ vm.assertFalse(data, err);
+ }
+ }
+
+ function assertEq(bool left, bool right) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right);
+ }
+ }
+
+ function assertEq(bool left, bool right, string memory err) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right, err);
+ }
+ }
+
+ function assertEq(uint256 left, uint256 right) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right);
+ }
+ }
+
+ function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right, err);
+ }
+ }
+
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals);
+ }
+
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals, err);
+ }
+
+ function assertEq(int256 left, int256 right) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right);
+ }
+ }
+
+ function assertEq(int256 left, int256 right, string memory err) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right, err);
+ }
+ }
+
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals);
+ }
+
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals, err);
+ }
+
+ function assertEq(address left, address right) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right);
+ }
+ }
+
+ function assertEq(address left, address right, string memory err) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right, err);
+ }
+ }
+
+ function assertEq(bytes32 left, bytes32 right) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right);
+ }
+ }
+
+ function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right, err);
+ }
+ }
+
+ function assertEq32(bytes32 left, bytes32 right) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right);
+ }
+ }
+
+ function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ if (left != right) {
+ vm.assertEq(left, right, err);
+ }
+ }
+
+ function assertEq(string memory left, string memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(string memory left, string memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes memory left, bytes memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bool[] memory left, bool[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(int256[] memory left, int256[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(address[] memory left, address[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(string[] memory left, string[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ // Legacy helper
+ function assertEqUint(uint256 left, uint256 right) internal pure virtual {
+ assertEq(left, right);
+ }
+
+ function assertNotEq(bool left, bool right) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right);
+ }
+ }
+
+ function assertNotEq(bool left, bool right, string memory err) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right, err);
+ }
+ }
+
+ function assertNotEq(uint256 left, uint256 right) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right);
+ }
+ }
+
+ function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right, err);
+ }
+ }
+
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertNotEqDecimal(left, right, decimals);
+ }
+
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err)
+ internal
+ pure
+ virtual
+ {
+ vm.assertNotEqDecimal(left, right, decimals, err);
+ }
+
+ function assertNotEq(int256 left, int256 right) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right);
+ }
+ }
+
+ function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right, err);
+ }
+ }
+
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertNotEqDecimal(left, right, decimals);
+ }
+
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertNotEqDecimal(left, right, decimals, err);
+ }
+
+ function assertNotEq(address left, address right) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right);
+ }
+ }
+
+ function assertNotEq(address left, address right, string memory err) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right, err);
+ }
+ }
+
+ function assertNotEq(bytes32 left, bytes32 right) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right);
+ }
+ }
+
+ function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right, err);
+ }
+ }
+
+ function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right);
+ }
+ }
+
+ function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ if (left == right) {
+ vm.assertNotEq(left, right, err);
+ }
+ }
+
+ function assertNotEq(string memory left, string memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes memory left, bytes memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(address[] memory left, address[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(string[] memory left, string[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertLt(uint256 left, uint256 right) internal pure virtual {
+ if (left >= right) {
+ vm.assertLt(left, right);
+ }
+ }
+
+ function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual {
+ if (left >= right) {
+ vm.assertLt(left, right, err);
+ }
+ }
+
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals);
+ }
+
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals, err);
+ }
+
+ function assertLt(int256 left, int256 right) internal pure virtual {
+ if (left >= right) {
+ vm.assertLt(left, right);
+ }
+ }
+
+ function assertLt(int256 left, int256 right, string memory err) internal pure virtual {
+ if (left >= right) {
+ vm.assertLt(left, right, err);
+ }
+ }
+
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals);
+ }
+
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals, err);
+ }
+
+ function assertGt(uint256 left, uint256 right) internal pure virtual {
+ if (left <= right) {
+ vm.assertGt(left, right);
+ }
+ }
+
+ function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual {
+ if (left <= right) {
+ vm.assertGt(left, right, err);
+ }
+ }
+
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals);
+ }
+
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals, err);
+ }
+
+ function assertGt(int256 left, int256 right) internal pure virtual {
+ if (left <= right) {
+ vm.assertGt(left, right);
+ }
+ }
+
+ function assertGt(int256 left, int256 right, string memory err) internal pure virtual {
+ if (left <= right) {
+ vm.assertGt(left, right, err);
+ }
+ }
+
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals);
+ }
+
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals, err);
+ }
+
+ function assertLe(uint256 left, uint256 right) internal pure virtual {
+ if (left > right) {
+ vm.assertLe(left, right);
+ }
+ }
+
+ function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual {
+ if (left > right) {
+ vm.assertLe(left, right, err);
+ }
+ }
+
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals);
+ }
+
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals, err);
+ }
+
+ function assertLe(int256 left, int256 right) internal pure virtual {
+ if (left > right) {
+ vm.assertLe(left, right);
+ }
+ }
+
+ function assertLe(int256 left, int256 right, string memory err) internal pure virtual {
+ if (left > right) {
+ vm.assertLe(left, right, err);
+ }
+ }
+
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals);
+ }
+
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals, err);
+ }
+
+ function assertGe(uint256 left, uint256 right) internal pure virtual {
+ if (left < right) {
+ vm.assertGe(left, right);
+ }
+ }
+
+ function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual {
+ if (left < right) {
+ vm.assertGe(left, right, err);
+ }
+ }
+
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals);
+ }
+
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals, err);
+ }
+
+ function assertGe(int256 left, int256 right) internal pure virtual {
+ if (left < right) {
+ vm.assertGe(left, right);
+ }
+ }
+
+ function assertGe(int256 left, int256 right, string memory err) internal pure virtual {
+ if (left < right) {
+ vm.assertGe(left, right, err);
+ }
+ }
+
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals);
+ }
+
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals, err);
+ }
+
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual {
+ vm.assertApproxEqAbs(left, right, maxDelta);
+ }
+
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbs(left, right, maxDelta, err);
+ }
+
+ function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
+ }
+
+ function assertApproxEqAbsDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxDelta,
+ uint256 decimals,
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
+ }
+
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual {
+ vm.assertApproxEqAbs(left, right, maxDelta);
+ }
+
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual {
+ vm.assertApproxEqAbs(left, right, maxDelta, err);
+ }
+
+ function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
+ }
+
+ function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
+ }
+
+ function assertApproxEqRel(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
+ ) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta);
+ }
+
+ function assertApproxEqRel(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta, err);
+ }
+
+ function assertApproxEqRelDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
+ }
+
+ function assertApproxEqRelDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals,
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
+ }
+
+ function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta);
+ }
+
+ function assertApproxEqRel(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta, err);
+ }
+
+ function assertApproxEqRelDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
+ }
+
+ function assertApproxEqRelDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals,
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
+ }
+
+ // Inherited from DSTest, not used but kept for backwards-compatibility
+ function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) {
+ return keccak256(left) == keccak256(right);
+ }
+
+ function assertEq0(bytes memory left, bytes memory right) internal pure virtual {
+ assertEq(left, right);
+ }
+
+ function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ assertEq(left, right, err);
+ }
+
+ function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual {
+ assertNotEq(left, right);
+ }
+
+ function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ assertNotEq(left, right, err);
+ }
+
+ function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {
+ assertEqCall(target, callDataA, target, callDataB, true);
+ }
+
+ function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)
+ internal
+ virtual
+ {
+ assertEqCall(targetA, callDataA, targetB, callDataB, true);
+ }
+
+ function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)
+ internal
+ virtual
+ {
+ assertEqCall(target, callDataA, target, callDataB, strictRevertData);
+ }
+
+ function assertEqCall(
+ address targetA,
+ bytes memory callDataA,
+ address targetB,
+ bytes memory callDataB,
+ bool strictRevertData
+ ) internal virtual {
+ (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);
+ (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);
+
+ if (successA && successB) {
+ assertEq(returnDataA, returnDataB, "Call return data does not match");
+ }
+
+ if (!successA && !successB && strictRevertData) {
+ assertEq(returnDataA, returnDataB, "Call revert data does not match");
+ }
+
+ if (!successA && successB) {
+ emit log("Error: Calls were not equal");
+ emit log_named_bytes(" Left call revert data", returnDataA);
+ emit log_named_bytes(" Right call return data", returnDataB);
+ revert("assertion failed");
+ }
+
+ if (successA && !successB) {
+ emit log("Error: Calls were not equal");
+ emit log_named_bytes(" Left call return data", returnDataA);
+ emit log_named_bytes(" Right call revert data", returnDataB);
+ revert("assertion failed");
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdChains.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdChains.sol
new file mode 100644
index 000000000..3bc5f43af
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdChains.sol
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import {VmSafe} from "./Vm.sol";
+
+/**
+ * StdChains provides information about EVM compatible chains that can be used in scripts/tests.
+ * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
+ * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
+ * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
+ * alias used in this contract, which can be found as the first argument to the
+ * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
+ *
+ * There are two main ways to use this contract:
+ * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
+ * `setChain(string memory chainAlias, Chain memory chain)`
+ * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
+ *
+ * The first time either of those are used, chains are initialized with the default set of RPC URLs.
+ * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
+ * `defaultRpcUrls`.
+ *
+ * The `setChain` function is straightforward, and it simply saves off the given chain data.
+ *
+ * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
+ * we want to retrieve the RPC URL for `mainnet`:
+ * - If you have specified data with `setChain`, it will return that.
+ * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
+ * is valid (e.g. a URL is specified, or an environment variable is given and exists).
+ * - If neither of the above conditions is met, the default data is returned.
+ *
+ * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
+ */
+abstract contract StdChains {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ bool private stdChainsInitialized;
+
+ struct ChainData {
+ string name;
+ uint256 chainId;
+ string rpcUrl;
+ }
+
+ struct Chain {
+ // The chain name.
+ string name;
+ // The chain's Chain ID.
+ uint256 chainId;
+ // The chain's alias. (i.e. what gets specified in `foundry.toml`).
+ string chainAlias;
+ // A default RPC endpoint for this chain.
+ // NOTE: This default RPC URL is included for convenience to facilitate quick tests and
+ // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy
+ // usage as you will be throttled and this is a disservice to others who need this endpoint.
+ string rpcUrl;
+ }
+
+ // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.
+ mapping(string => Chain) private chains;
+ // Maps from the chain's alias to it's default RPC URL.
+ mapping(string => string) private defaultRpcUrls;
+ // Maps from a chain ID to it's alias.
+ mapping(uint256 => string) private idToAlias;
+
+ bool private fallbackToDefaultRpcUrls = true;
+
+ // The RPC URL will be fetched from config or defaultRpcUrls if possible.
+ function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
+ require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");
+
+ initializeStdChains();
+ chain = chains[chainAlias];
+ require(
+ chain.chainId != 0,
+ string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
+ );
+
+ chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
+ }
+
+ function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
+ require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
+ initializeStdChains();
+ string memory chainAlias = idToAlias[chainId];
+
+ chain = chains[chainAlias];
+
+ require(
+ chain.chainId != 0,
+ string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
+ );
+
+ chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
+ }
+
+ // set chain info, with priority to argument's rpcUrl field.
+ function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
+ require(
+ bytes(chainAlias).length != 0,
+ "StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
+ );
+
+ require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
+
+ initializeStdChains();
+ string memory foundAlias = idToAlias[chain.chainId];
+
+ require(
+ bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),
+ string(
+ abi.encodePacked(
+ "StdChains setChain(string,ChainData): Chain ID ",
+ vm.toString(chain.chainId),
+ " already used by \"",
+ foundAlias,
+ "\"."
+ )
+ )
+ );
+
+ uint256 oldChainId = chains[chainAlias].chainId;
+ delete idToAlias[oldChainId];
+
+ chains[chainAlias] =
+ Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
+ idToAlias[chain.chainId] = chainAlias;
+ }
+
+ // set chain info, with priority to argument's rpcUrl field.
+ function setChain(string memory chainAlias, Chain memory chain) internal virtual {
+ setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
+ }
+
+ function _toUpper(string memory str) private pure returns (string memory) {
+ bytes memory strb = bytes(str);
+ bytes memory copy = new bytes(strb.length);
+ for (uint256 i = 0; i < strb.length; i++) {
+ bytes1 b = strb[i];
+ if (b >= 0x61 && b <= 0x7A) {
+ copy[i] = bytes1(uint8(b) - 32);
+ } else {
+ copy[i] = b;
+ }
+ }
+ return string(copy);
+ }
+
+ // lookup rpcUrl, in descending order of priority:
+ // current -> config (foundry.toml) -> environment variable -> default
+ function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)
+ private
+ view
+ returns (Chain memory)
+ {
+ if (bytes(chain.rpcUrl).length == 0) {
+ try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
+ chain.rpcUrl = configRpcUrl;
+ } catch (bytes memory err) {
+ string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
+ if (fallbackToDefaultRpcUrls) {
+ chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
+ } else {
+ chain.rpcUrl = vm.envString(envName);
+ }
+ // Distinguish 'not found' from 'cannot read'
+ // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions
+ bytes memory oldNotFoundError =
+ abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
+ bytes memory newNotFoundError = abi.encodeWithSignature(
+ "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
+ );
+ bytes32 errHash = keccak256(err);
+ if (
+ (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError))
+ || bytes(chain.rpcUrl).length == 0
+ ) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ revert(add(32, err), mload(err))
+ }
+ }
+ }
+ }
+ return chain;
+ }
+
+ function setFallbackToDefaultRpcUrls(bool useDefault) internal {
+ fallbackToDefaultRpcUrls = useDefault;
+ }
+
+ function initializeStdChains() private {
+ if (stdChainsInitialized) return;
+
+ stdChainsInitialized = true;
+
+ // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol`
+ setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
+ setChainWithDefaultRpcUrl("mainnet", ChainData("Mainnet", 1, "https://eth.llamarpc.com"));
+ setChainWithDefaultRpcUrl(
+ "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
+ );
+ setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
+ setChainWithDefaultRpcUrl("hoodi", ChainData("Hoodi", 560048, "https://rpc.hoodi.ethpandaops.io"));
+ setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
+ setChainWithDefaultRpcUrl(
+ "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
+ );
+ setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
+ setChainWithDefaultRpcUrl(
+ "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
+ );
+ setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
+ setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
+ setChainWithDefaultRpcUrl(
+ "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
+ );
+ setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
+ setChainWithDefaultRpcUrl(
+ "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
+ );
+ setChainWithDefaultRpcUrl(
+ "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
+ );
+ setChainWithDefaultRpcUrl(
+ "bnb_smart_chain_testnet",
+ ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
+ );
+ setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
+ setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
+ setChainWithDefaultRpcUrl(
+ "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
+ );
+ setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
+ setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
+ setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
+ setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io"));
+ setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io"));
+ setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/"));
+ setChainWithDefaultRpcUrl(
+ "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/")
+ );
+ setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
+ setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
+ setChainWithDefaultRpcUrl(
+ "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com")
+ );
+ setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc"));
+ setChainWithDefaultRpcUrl(
+ "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc")
+ );
+
+ setChainWithDefaultRpcUrl("mode", ChainData("Mode", 34443, "https://mode.drpc.org"));
+ setChainWithDefaultRpcUrl("mode_sepolia", ChainData("Mode Sepolia", 919, "https://sepolia.mode.network"));
+
+ setChainWithDefaultRpcUrl("zora", ChainData("Zora", 7777777, "https://zora.drpc.org"));
+ setChainWithDefaultRpcUrl(
+ "zora_sepolia", ChainData("Zora Sepolia", 999999999, "https://sepolia.rpc.zora.energy")
+ );
+
+ setChainWithDefaultRpcUrl("race", ChainData("Race", 6805, "https://racemainnet.io"));
+ setChainWithDefaultRpcUrl("race_sepolia", ChainData("Race Sepolia", 6806, "https://racemainnet.io"));
+
+ setChainWithDefaultRpcUrl("metal", ChainData("Metal", 1750, "https://metall2.drpc.org"));
+ setChainWithDefaultRpcUrl("metal_sepolia", ChainData("Metal Sepolia", 1740, "https://testnet.rpc.metall2.com"));
+
+ setChainWithDefaultRpcUrl("binary", ChainData("Binary", 624, "https://rpc.zero.thebinaryholdings.com"));
+ setChainWithDefaultRpcUrl(
+ "binary_sepolia", ChainData("Binary Sepolia", 625, "https://rpc.zero.thebinaryholdings.com")
+ );
+
+ setChainWithDefaultRpcUrl("orderly", ChainData("Orderly", 291, "https://rpc.orderly.network"));
+ setChainWithDefaultRpcUrl(
+ "orderly_sepolia", ChainData("Orderly Sepolia", 4460, "https://testnet-rpc.orderly.org")
+ );
+ }
+
+ // set chain info, with priority to chainAlias' rpc url in foundry.toml
+ function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
+ string memory rpcUrl = chain.rpcUrl;
+ defaultRpcUrls[chainAlias] = rpcUrl;
+ chain.rpcUrl = "";
+ setChain(chainAlias, chain);
+ chain.rpcUrl = rpcUrl; // restore argument
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdCheats.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdCheats.sol
new file mode 100644
index 000000000..9f360dec2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdCheats.sol
@@ -0,0 +1,829 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {StdStorage, stdStorage} from "./StdStorage.sol";
+import {console2} from "./console2.sol";
+import {Vm} from "./Vm.sol";
+
+abstract contract StdCheatsSafe {
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ uint256 private constant UINT256_MAX =
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ bool private gasMeteringOff;
+
+ // Data structures to parse Transaction objects from the broadcast artifact
+ // that conform to EIP1559. The Raw structs is what is parsed from the JSON
+ // and then converted to the one that is used by the user for better UX.
+
+ struct RawTx1559 {
+ string[] arguments;
+ address contractAddress;
+ string contractName;
+ // json value name = function
+ string functionSig;
+ bytes32 hash;
+ // json value name = tx
+ RawTx1559Detail txDetail;
+ // json value name = type
+ string opcode;
+ }
+
+ struct RawTx1559Detail {
+ AccessList[] accessList;
+ bytes data;
+ address from;
+ bytes gas;
+ bytes nonce;
+ address to;
+ bytes txType;
+ bytes value;
+ }
+
+ struct Tx1559 {
+ string[] arguments;
+ address contractAddress;
+ string contractName;
+ string functionSig;
+ bytes32 hash;
+ Tx1559Detail txDetail;
+ string opcode;
+ }
+
+ struct Tx1559Detail {
+ AccessList[] accessList;
+ bytes data;
+ address from;
+ uint256 gas;
+ uint256 nonce;
+ address to;
+ uint256 txType;
+ uint256 value;
+ }
+
+ // Data structures to parse Transaction objects from the broadcast artifact
+ // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
+ // and then converted to the one that is used by the user for better UX.
+
+ struct TxLegacy {
+ string[] arguments;
+ address contractAddress;
+ string contractName;
+ string functionSig;
+ string hash;
+ string opcode;
+ TxDetailLegacy transaction;
+ }
+
+ struct TxDetailLegacy {
+ AccessList[] accessList;
+ uint256 chainId;
+ bytes data;
+ address from;
+ uint256 gas;
+ uint256 gasPrice;
+ bytes32 hash;
+ uint256 nonce;
+ bytes1 opcode;
+ bytes32 r;
+ bytes32 s;
+ uint256 txType;
+ address to;
+ uint8 v;
+ uint256 value;
+ }
+
+ struct AccessList {
+ address accessAddress;
+ bytes32[] storageKeys;
+ }
+
+ // Data structures to parse Receipt objects from the broadcast artifact.
+ // The Raw structs is what is parsed from the JSON
+ // and then converted to the one that is used by the user for better UX.
+
+ struct RawReceipt {
+ bytes32 blockHash;
+ bytes blockNumber;
+ address contractAddress;
+ bytes cumulativeGasUsed;
+ bytes effectiveGasPrice;
+ address from;
+ bytes gasUsed;
+ RawReceiptLog[] logs;
+ bytes logsBloom;
+ bytes status;
+ address to;
+ bytes32 transactionHash;
+ bytes transactionIndex;
+ }
+
+ struct Receipt {
+ bytes32 blockHash;
+ uint256 blockNumber;
+ address contractAddress;
+ uint256 cumulativeGasUsed;
+ uint256 effectiveGasPrice;
+ address from;
+ uint256 gasUsed;
+ ReceiptLog[] logs;
+ bytes logsBloom;
+ uint256 status;
+ address to;
+ bytes32 transactionHash;
+ uint256 transactionIndex;
+ }
+
+ // Data structures to parse the entire broadcast artifact, assuming the
+ // transactions conform to EIP1559.
+
+ struct EIP1559ScriptArtifact {
+ string[] libraries;
+ string path;
+ string[] pending;
+ Receipt[] receipts;
+ uint256 timestamp;
+ Tx1559[] transactions;
+ TxReturn[] txReturns;
+ }
+
+ struct RawEIP1559ScriptArtifact {
+ string[] libraries;
+ string path;
+ string[] pending;
+ RawReceipt[] receipts;
+ TxReturn[] txReturns;
+ uint256 timestamp;
+ RawTx1559[] transactions;
+ }
+
+ struct RawReceiptLog {
+ // json value = address
+ address logAddress;
+ bytes32 blockHash;
+ bytes blockNumber;
+ bytes data;
+ bytes logIndex;
+ bool removed;
+ bytes32[] topics;
+ bytes32 transactionHash;
+ bytes transactionIndex;
+ bytes transactionLogIndex;
+ }
+
+ struct ReceiptLog {
+ // json value = address
+ address logAddress;
+ bytes32 blockHash;
+ uint256 blockNumber;
+ bytes data;
+ uint256 logIndex;
+ bytes32[] topics;
+ uint256 transactionIndex;
+ uint256 transactionLogIndex;
+ bool removed;
+ }
+
+ struct TxReturn {
+ string internalType;
+ string value;
+ }
+
+ struct Account {
+ address addr;
+ uint256 key;
+ }
+
+ enum AddressType {
+ Payable,
+ NonPayable,
+ ZeroAddress,
+ Precompile,
+ ForgeAddress
+ }
+
+ // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
+ function assumeNotBlacklisted(address token, address addr) internal view virtual {
+ // Nothing to check if `token` is not a contract.
+ uint256 tokenCodeSize;
+ assembly {
+ tokenCodeSize := extcodesize(token)
+ }
+ require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
+
+ bool success;
+ bytes memory returnData;
+
+ // 4-byte selector for `isBlacklisted(address)`, used by USDC.
+ (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
+ vm.assume(!success || abi.decode(returnData, (bool)) == false);
+
+ // 4-byte selector for `isBlackListed(address)`, used by USDT.
+ (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
+ vm.assume(!success || abi.decode(returnData, (bool)) == false);
+ }
+
+ // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
+ // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
+ // backwards compatibility, since this name was used in the original PR which already has
+ // a release. This function can be removed in a future release once we want a breaking change.
+ function assumeNoBlacklisted(address token, address addr) internal view virtual {
+ assumeNotBlacklisted(token, addr);
+ }
+
+ function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
+ if (addressType == AddressType.Payable) {
+ assumeNotPayable(addr);
+ } else if (addressType == AddressType.NonPayable) {
+ assumePayable(addr);
+ } else if (addressType == AddressType.ZeroAddress) {
+ assumeNotZeroAddress(addr);
+ } else if (addressType == AddressType.Precompile) {
+ assumeNotPrecompile(addr);
+ } else if (addressType == AddressType.ForgeAddress) {
+ assumeNotForgeAddress(addr);
+ }
+ }
+
+ function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
+ assumeAddressIsNot(addr, addressType1);
+ assumeAddressIsNot(addr, addressType2);
+ }
+
+ function assumeAddressIsNot(
+ address addr,
+ AddressType addressType1,
+ AddressType addressType2,
+ AddressType addressType3
+ ) internal virtual {
+ assumeAddressIsNot(addr, addressType1);
+ assumeAddressIsNot(addr, addressType2);
+ assumeAddressIsNot(addr, addressType3);
+ }
+
+ function assumeAddressIsNot(
+ address addr,
+ AddressType addressType1,
+ AddressType addressType2,
+ AddressType addressType3,
+ AddressType addressType4
+ ) internal virtual {
+ assumeAddressIsNot(addr, addressType1);
+ assumeAddressIsNot(addr, addressType2);
+ assumeAddressIsNot(addr, addressType3);
+ assumeAddressIsNot(addr, addressType4);
+ }
+
+ // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
+ // `addr` and checking the `success` return value.
+ // NOTE: This function may result in state changes depending on the fallback/receive logic
+ // implemented by `addr`, which should be taken into account when this function is used.
+ function _isPayable(address addr) private returns (bool) {
+ require(
+ addr.balance < UINT256_MAX,
+ "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
+ );
+ uint256 origBalanceTest = address(this).balance;
+ uint256 origBalanceAddr = address(addr).balance;
+
+ vm.deal(address(this), 1);
+ (bool success,) = payable(addr).call{value: 1}("");
+
+ // reset balances
+ vm.deal(address(this), origBalanceTest);
+ vm.deal(addr, origBalanceAddr);
+
+ return success;
+ }
+
+ // NOTE: This function may result in state changes depending on the fallback/receive logic
+ // implemented by `addr`, which should be taken into account when this function is used. See the
+ // `_isPayable` method for more information.
+ function assumePayable(address addr) internal virtual {
+ vm.assume(_isPayable(addr));
+ }
+
+ function assumeNotPayable(address addr) internal virtual {
+ vm.assume(!_isPayable(addr));
+ }
+
+ function assumeNotZeroAddress(address addr) internal pure virtual {
+ vm.assume(addr != address(0));
+ }
+
+ function assumeNotPrecompile(address addr) internal pure virtual {
+ assumeNotPrecompile(addr, _pureChainId());
+ }
+
+ function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
+ // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
+ // address), but the same rationale for excluding them applies so we include those too.
+
+ // These are reserved by Ethereum and may be on all EVM-compatible chains.
+ vm.assume(addr < address(0x1) || addr > address(0xff));
+
+ // forgefmt: disable-start
+ if (chainId == 10 || chainId == 420) {
+ // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
+ vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
+ } else if (chainId == 42161 || chainId == 421613) {
+ // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
+ vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
+ } else if (chainId == 43114 || chainId == 43113) {
+ // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
+ vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
+ vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
+ vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
+ }
+ // forgefmt: disable-end
+ }
+
+ function assumeNotForgeAddress(address addr) internal pure virtual {
+ // vm, console, and Create2Deployer addresses
+ vm.assume(
+ addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
+ && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
+ );
+ }
+
+ function assumeUnusedAddress(address addr) internal view virtual {
+ uint256 size;
+ assembly {
+ size := extcodesize(addr)
+ }
+ vm.assume(size == 0);
+
+ assumeNotPrecompile(addr);
+ assumeNotZeroAddress(addr);
+ assumeNotForgeAddress(addr);
+ }
+
+ function readEIP1559ScriptArtifact(string memory path)
+ internal
+ view
+ virtual
+ returns (EIP1559ScriptArtifact memory)
+ {
+ string memory data = vm.readFile(path);
+ bytes memory parsedData = vm.parseJson(data);
+ RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
+ EIP1559ScriptArtifact memory artifact;
+ artifact.libraries = rawArtifact.libraries;
+ artifact.path = rawArtifact.path;
+ artifact.timestamp = rawArtifact.timestamp;
+ artifact.pending = rawArtifact.pending;
+ artifact.txReturns = rawArtifact.txReturns;
+ artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
+ artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
+ return artifact;
+ }
+
+ function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
+ Tx1559[] memory txs = new Tx1559[](rawTxs.length);
+ for (uint256 i; i < rawTxs.length; i++) {
+ txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
+ }
+ return txs;
+ }
+
+ function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
+ Tx1559 memory transaction;
+ transaction.arguments = rawTx.arguments;
+ transaction.contractName = rawTx.contractName;
+ transaction.functionSig = rawTx.functionSig;
+ transaction.hash = rawTx.hash;
+ transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
+ transaction.opcode = rawTx.opcode;
+ return transaction;
+ }
+
+ function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
+ internal
+ pure
+ virtual
+ returns (Tx1559Detail memory)
+ {
+ Tx1559Detail memory txDetail;
+ txDetail.data = rawDetail.data;
+ txDetail.from = rawDetail.from;
+ txDetail.to = rawDetail.to;
+ txDetail.nonce = _bytesToUint(rawDetail.nonce);
+ txDetail.txType = _bytesToUint(rawDetail.txType);
+ txDetail.value = _bytesToUint(rawDetail.value);
+ txDetail.gas = _bytesToUint(rawDetail.gas);
+ txDetail.accessList = rawDetail.accessList;
+ return txDetail;
+ }
+
+ function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
+ string memory deployData = vm.readFile(path);
+ bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
+ RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
+ return rawToConvertedEIPTx1559s(rawTxs);
+ }
+
+ function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
+ string memory deployData = vm.readFile(path);
+ string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
+ bytes memory parsedDeployData = vm.parseJson(deployData, key);
+ RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
+ return rawToConvertedEIPTx1559(rawTx);
+ }
+
+ // Analogous to readTransactions, but for receipts.
+ function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
+ string memory deployData = vm.readFile(path);
+ bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
+ RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
+ return rawToConvertedReceipts(rawReceipts);
+ }
+
+ function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
+ string memory deployData = vm.readFile(path);
+ string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
+ bytes memory parsedDeployData = vm.parseJson(deployData, key);
+ RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
+ return rawToConvertedReceipt(rawReceipt);
+ }
+
+ function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
+ Receipt[] memory receipts = new Receipt[](rawReceipts.length);
+ for (uint256 i; i < rawReceipts.length; i++) {
+ receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
+ }
+ return receipts;
+ }
+
+ function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
+ Receipt memory receipt;
+ receipt.blockHash = rawReceipt.blockHash;
+ receipt.to = rawReceipt.to;
+ receipt.from = rawReceipt.from;
+ receipt.contractAddress = rawReceipt.contractAddress;
+ receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
+ receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
+ receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
+ receipt.status = _bytesToUint(rawReceipt.status);
+ receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
+ receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
+ receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
+ receipt.logsBloom = rawReceipt.logsBloom;
+ receipt.transactionHash = rawReceipt.transactionHash;
+ return receipt;
+ }
+
+ function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
+ internal
+ pure
+ virtual
+ returns (ReceiptLog[] memory)
+ {
+ ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
+ for (uint256 i; i < rawLogs.length; i++) {
+ logs[i].logAddress = rawLogs[i].logAddress;
+ logs[i].blockHash = rawLogs[i].blockHash;
+ logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
+ logs[i].data = rawLogs[i].data;
+ logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
+ logs[i].topics = rawLogs[i].topics;
+ logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
+ logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
+ logs[i].removed = rawLogs[i].removed;
+ }
+ return logs;
+ }
+
+ // Deploy a contract by fetching the contract bytecode from
+ // the artifacts directory
+ // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
+ function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
+ bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(0, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
+ }
+
+ function deployCode(string memory what) internal virtual returns (address addr) {
+ bytes memory bytecode = vm.getCode(what);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(0, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
+ }
+
+ /// @dev deploy contract with value on construction
+ function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
+ bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(val, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
+ }
+
+ function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
+ bytes memory bytecode = vm.getCode(what);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(val, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
+ }
+
+ // creates a labeled address and the corresponding private key
+ function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
+ privateKey = uint256(keccak256(abi.encodePacked(name)));
+ addr = vm.addr(privateKey);
+ vm.label(addr, name);
+ }
+
+ // creates a labeled address
+ function makeAddr(string memory name) internal virtual returns (address addr) {
+ (addr,) = makeAddrAndKey(name);
+ }
+
+ // Destroys an account immediately, sending the balance to beneficiary.
+ // Destroying means: balance will be zero, code will be empty, and nonce will be 0
+ // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
+ // only after tx ends, this will run immediately.
+ function destroyAccount(address who, address beneficiary) internal virtual {
+ uint256 currBalance = who.balance;
+ vm.etch(who, abi.encode());
+ vm.deal(who, 0);
+ vm.resetNonce(who);
+
+ uint256 beneficiaryBalance = beneficiary.balance;
+ vm.deal(beneficiary, currBalance + beneficiaryBalance);
+ }
+
+ // creates a struct containing both a labeled address and the corresponding private key
+ function makeAccount(string memory name) internal virtual returns (Account memory account) {
+ (account.addr, account.key) = makeAddrAndKey(name);
+ }
+
+ function deriveRememberKey(string memory mnemonic, uint32 index)
+ internal
+ virtual
+ returns (address who, uint256 privateKey)
+ {
+ privateKey = vm.deriveKey(mnemonic, index);
+ who = vm.rememberKey(privateKey);
+ }
+
+ function _bytesToUint(bytes memory b) private pure returns (uint256) {
+ require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
+ return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
+ }
+
+ function isFork() internal view virtual returns (bool status) {
+ try vm.activeFork() {
+ status = true;
+ } catch (bytes memory) {}
+ }
+
+ modifier skipWhenForking() {
+ if (!isFork()) {
+ _;
+ }
+ }
+
+ modifier skipWhenNotForking() {
+ if (isFork()) {
+ _;
+ }
+ }
+
+ modifier noGasMetering() {
+ vm.pauseGasMetering();
+ // To prevent turning gas monitoring back on with nested functions that use this modifier,
+ // we check if gasMetering started in the off position. If it did, we don't want to turn
+ // it back on until we exit the top level function that used the modifier
+ //
+ // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
+ // funcA will have `gasStartedOff` as false, funcB will have it as true,
+ // so we only turn metering back on at the end of the funcA
+ bool gasStartedOff = gasMeteringOff;
+ gasMeteringOff = true;
+
+ _;
+
+ // if gas metering was on when this modifier was called, turn it back on at the end
+ if (!gasStartedOff) {
+ gasMeteringOff = false;
+ vm.resumeGasMetering();
+ }
+ }
+
+ // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
+ // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
+ // can't simply access the chain ID in a normal view or pure function because the solc View Pure
+ // Checker changed `chainid` from pure to view in 0.8.0.
+ function _viewChainId() private view returns (uint256 chainId) {
+ // Assembly required since `block.chainid` was introduced in 0.8.0.
+ assembly {
+ chainId := chainid()
+ }
+
+ address(this); // Silence warnings in older Solc versions.
+ }
+
+ function _pureChainId() private pure returns (uint256 chainId) {
+ function() internal view returns (uint256) fnIn = _viewChainId;
+ function() internal pure returns (uint256) pureChainId;
+ assembly {
+ pureChainId := fnIn
+ }
+ chainId = pureChainId();
+ }
+}
+
+// Wrappers around cheatcodes to avoid footguns
+abstract contract StdCheats is StdCheatsSafe {
+ using stdStorage for StdStorage;
+
+ StdStorage private stdstore;
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+ address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
+
+ // Skip forward or rewind time by the specified number of seconds
+ function skip(uint256 time) internal virtual {
+ vm.warp(vm.getBlockTimestamp() + time);
+ }
+
+ function rewind(uint256 time) internal virtual {
+ vm.warp(vm.getBlockTimestamp() - time);
+ }
+
+ // Setup a prank from an address that has some ether
+ function hoax(address msgSender) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.prank(msgSender);
+ }
+
+ function hoax(address msgSender, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.prank(msgSender);
+ }
+
+ function hoax(address msgSender, address origin) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.prank(msgSender, origin);
+ }
+
+ function hoax(address msgSender, address origin, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.prank(msgSender, origin);
+ }
+
+ // Start perpetual prank from an address that has some ether
+ function startHoax(address msgSender) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.startPrank(msgSender);
+ }
+
+ function startHoax(address msgSender, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.startPrank(msgSender);
+ }
+
+ // Start perpetual prank from an address that has some ether
+ // tx.origin is set to the origin parameter
+ function startHoax(address msgSender, address origin) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.startPrank(msgSender, origin);
+ }
+
+ function startHoax(address msgSender, address origin, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.startPrank(msgSender, origin);
+ }
+
+ function changePrank(address msgSender) internal virtual {
+ console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
+ vm.stopPrank();
+ vm.startPrank(msgSender);
+ }
+
+ function changePrank(address msgSender, address txOrigin) internal virtual {
+ vm.stopPrank();
+ vm.startPrank(msgSender, txOrigin);
+ }
+
+ // The same as Vm's `deal`
+ // Use the alternative signature for ERC20 tokens
+ function deal(address to, uint256 give) internal virtual {
+ vm.deal(to, give);
+ }
+
+ // Set the balance of an account for any ERC20 token
+ // Use the alternative signature to update `totalSupply`
+ function deal(address token, address to, uint256 give) internal virtual {
+ deal(token, to, give, false);
+ }
+
+ // Set the balance of an account for any ERC1155 token
+ // Use the alternative signature to update `totalSupply`
+ function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
+ dealERC1155(token, to, id, give, false);
+ }
+
+ function deal(address token, address to, uint256 give, bool adjust) internal virtual {
+ // get current balance
+ (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
+ uint256 prevBal = abi.decode(balData, (uint256));
+
+ // update balance
+ stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
+
+ // update total supply
+ if (adjust) {
+ (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
+ uint256 totSup = abi.decode(totSupData, (uint256));
+ if (give < prevBal) {
+ totSup -= (prevBal - give);
+ } else {
+ totSup += (give - prevBal);
+ }
+ stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
+ }
+ }
+
+ function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
+ // get current balance
+ (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
+ uint256 prevBal = abi.decode(balData, (uint256));
+
+ // update balance
+ stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
+
+ // update total supply
+ if (adjust) {
+ (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
+ require(
+ totSupData.length != 0,
+ "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
+ );
+ uint256 totSup = abi.decode(totSupData, (uint256));
+ if (give < prevBal) {
+ totSup -= (prevBal - give);
+ } else {
+ totSup += (give - prevBal);
+ }
+ stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
+ }
+ }
+
+ function dealERC721(address token, address to, uint256 id) internal virtual {
+ // check if token id is already minted and the actual owner.
+ (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
+ require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
+
+ // get owner current balance
+ (, bytes memory fromBalData) =
+ token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
+ uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
+
+ // get new user current balance
+ (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
+ uint256 toPrevBal = abi.decode(toBalData, (uint256));
+
+ // update balances
+ stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
+ stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
+
+ // update owner
+ stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
+ }
+
+ function deployCodeTo(string memory what, address where) internal virtual {
+ deployCodeTo(what, "", 0, where);
+ }
+
+ function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
+ deployCodeTo(what, args, 0, where);
+ }
+
+ function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
+ bytes memory creationCode = vm.getCode(what);
+ vm.etch(where, abi.encodePacked(creationCode, args));
+ (bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
+ require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
+ vm.etch(where, runtimeBytecode);
+ }
+
+ // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
+ function console2_log_StdCheats(string memory p0) private view {
+ (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
+ status;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdConfig.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdConfig.sol
new file mode 100644
index 000000000..506ac34a5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdConfig.sol
@@ -0,0 +1,612 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+import {VmSafe} from "./Vm.sol";
+import {Variable, Type, TypeKind, LibVariable} from "./LibVariable.sol";
+
+/// @notice A contract that parses a toml configuration file and load its
+/// variables into storage, automatically casting them, on deployment.
+///
+/// @dev This contract assumes a toml structure where top-level keys
+/// represent chain ids or aliases. Under each chain key, variables are
+/// organized by type in separate sub-tables like `[.]`, where
+/// type must be: `bool`, `address`, `bytes32`, `uint`, `ìnt`, `string`, or `bytes`.
+///
+/// Supported format:
+/// ```
+/// [mainnet]
+/// endpoint_url = "${MAINNET_RPC}"
+///
+/// [mainnet.bool]
+/// is_live = true
+///
+/// [mainnet.address]
+/// weth = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
+/// whitelisted_admins = [
+/// "${MAINNET_ADMIN}",
+/// "0x00000000000000000000000000000000deadbeef",
+/// "0x000000000000000000000000000000c0ffeebabe"
+/// ]
+///
+/// [mainnet.uint]
+/// important_number = 123
+/// ```
+contract StdConfig {
+ using LibVariable for Type;
+ using LibVariable for TypeKind;
+
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ /// @dev Types: `bool`, `address`, `bytes32`, `uint`, `ìnt`, `string`, `bytes`.
+ uint8 private constant NUM_TYPES = 7;
+
+ // -- ERRORS ---------------------------------------------------------------
+
+ error AlreadyInitialized(string key);
+ error InvalidChainKey(string aliasOrId);
+ error ChainNotInitialized(uint256 chainId);
+ error UnableToParseVariable(string key);
+ error WriteToFileInForbiddenCtxt();
+
+ // -- STORAGE (CACHE FROM CONFIG FILE) ------------------------------------
+
+ /// @dev Path to the loaded TOML configuration file.
+ string private _filePath;
+
+ /// @dev List of top-level keys found in the TOML file, assumed to be chain names/aliases.
+ string[] private _chainKeys;
+
+ /// @dev Storage for the configured RPC URL for each chain.
+ mapping(uint256 => string) private _rpcOf;
+
+ /// @dev Storage for values, organized by chain ID and variable key.
+ mapping(uint256 => mapping(string => bytes)) private _dataOf;
+
+ /// @dev Type cache for runtime checking when casting.
+ mapping(uint256 => mapping(string => Type)) private _typeOf;
+
+ /// @dev When enabled, `set` will always write updates back to the configuration file.
+ /// Can only be enabled in a scripting context to prevent file corruption from
+ /// concurrent I/O access, as tests run in parallel.
+ bool private _writeToFile;
+
+ // -- CONSTRUCTOR ----------------------------------------------------------
+
+ /// @notice Reads the TOML file and iterates through each top-level key, which is
+ /// assumed to be a chain name or ID. For each chain, it caches its RPC
+ /// endpoint and all variables defined in typed sub-tables like `[.]`,
+ /// where type must be: `bool`, `address`, `uint`, `bytes32`, `string`, or `bytes`.
+ ///
+ /// The constructor attempts to parse each variable first as a single value,
+ /// and if that fails, as an array of that type. If a variable cannot be
+ /// parsed as either, the constructor will revert with an error.
+ ///
+ /// @param configFilePath: The local path to the TOML configuration file.
+ /// @param writeToFile: Whether to write updates back to the TOML file. Only for scripts.
+ constructor(string memory configFilePath, bool writeToFile) {
+ if (writeToFile && !vm.isContext(VmSafe.ForgeContext.ScriptGroup)) {
+ revert WriteToFileInForbiddenCtxt();
+ }
+
+ _filePath = configFilePath;
+ _writeToFile = writeToFile;
+ string memory content = vm.resolveEnv(vm.readFile(configFilePath));
+ string[] memory chain_keys = vm.parseTomlKeys(content, "$");
+
+ // Cache the entire configuration to storage
+ for (uint256 i = 0; i < chain_keys.length; i++) {
+ string memory chain_key = chain_keys[i];
+ // Ignore top-level keys that are not tables
+ if (vm.parseTomlKeys(content, string.concat("$.", chain_key)).length == 0) {
+ continue;
+ }
+ uint256 chainId = resolveChainId(chain_key);
+ _chainKeys.push(chain_key);
+
+ // Cache the configure rpc endpoint for that chain.
+ // Falls back to `[rpc_endpoints]`. Panics if no rpc endpoint is configured.
+ try vm.parseTomlString(content, string.concat("$.", chain_key, ".endpoint_url")) returns (string memory url)
+ {
+ _rpcOf[chainId] = vm.resolveEnv(url);
+ } catch {
+ _rpcOf[chainId] = vm.resolveEnv(vm.rpcUrl(chain_key));
+ }
+
+ // Iterate through all the available `TypeKind`s (except `None`) to create the sub-section paths
+ for (uint8 t = 1; t <= NUM_TYPES; t++) {
+ TypeKind ty = TypeKind(t);
+ string memory typePath = string.concat("$.", chain_key, ".", ty.toTomlKey());
+
+ try vm.parseTomlKeys(content, typePath) returns (string[] memory keys) {
+ for (uint256 j = 0; j < keys.length; j++) {
+ string memory key = keys[j];
+ if (_typeOf[chainId][key].kind == TypeKind.None) {
+ _loadAndCacheValue(content, string.concat(typePath, ".", key), chainId, key, ty);
+ } else {
+ revert AlreadyInitialized(key);
+ }
+ }
+ } catch {} // Section does not exist, ignore.
+ }
+ }
+ }
+
+ function _loadAndCacheValue(
+ string memory content,
+ string memory path,
+ uint256 chainId,
+ string memory key,
+ TypeKind ty
+ ) private {
+ bool success = false;
+ if (ty == TypeKind.Bool) {
+ try vm.parseTomlBool(content, path) returns (bool val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Bool, false);
+ success = true;
+ } catch {
+ try vm.parseTomlBoolArray(content, path) returns (bool[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Bool, true);
+ success = true;
+ } catch {}
+ }
+ } else if (ty == TypeKind.Address) {
+ try vm.parseTomlAddress(content, path) returns (address val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Address, false);
+ success = true;
+ } catch {
+ try vm.parseTomlAddressArray(content, path) returns (address[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Address, true);
+ success = true;
+ } catch {}
+ }
+ } else if (ty == TypeKind.Bytes32) {
+ try vm.parseTomlBytes32(content, path) returns (bytes32 val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Bytes32, false);
+ success = true;
+ } catch {
+ try vm.parseTomlBytes32Array(content, path) returns (bytes32[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Bytes32, true);
+ success = true;
+ } catch {}
+ }
+ } else if (ty == TypeKind.Uint256) {
+ try vm.parseTomlUint(content, path) returns (uint256 val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Uint256, false);
+ success = true;
+ } catch {
+ try vm.parseTomlUintArray(content, path) returns (uint256[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Uint256, true);
+ success = true;
+ } catch {}
+ }
+ } else if (ty == TypeKind.Int256) {
+ try vm.parseTomlInt(content, path) returns (int256 val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Int256, false);
+ success = true;
+ } catch {
+ try vm.parseTomlIntArray(content, path) returns (int256[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Int256, true);
+ success = true;
+ } catch {}
+ }
+ } else if (ty == TypeKind.Bytes) {
+ try vm.parseTomlBytes(content, path) returns (bytes memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Bytes, false);
+ success = true;
+ } catch {
+ try vm.parseTomlBytesArray(content, path) returns (bytes[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.Bytes, true);
+ success = true;
+ } catch {}
+ }
+ } else if (ty == TypeKind.String) {
+ try vm.parseTomlString(content, path) returns (string memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.String, false);
+ success = true;
+ } catch {
+ try vm.parseTomlStringArray(content, path) returns (string[] memory val) {
+ _dataOf[chainId][key] = abi.encode(val);
+ _typeOf[chainId][key] = Type(TypeKind.String, true);
+ success = true;
+ } catch {}
+ }
+ }
+
+ if (!success) {
+ revert UnableToParseVariable(key);
+ }
+ }
+
+ // -- HELPER FUNCTIONS -----------------------------------------------------
+
+ /// @notice Enable or disable automatic writing to the TOML file on `set`.
+ /// Can only be enabled when scripting.
+ function writeUpdatesBackToFile(bool enabled) public {
+ if (enabled && !vm.isContext(VmSafe.ForgeContext.ScriptGroup)) {
+ revert WriteToFileInForbiddenCtxt();
+ }
+
+ _writeToFile = enabled;
+ }
+
+ /// @notice Resolves a chain alias or a chain id string to its numerical chain id.
+ /// @param aliasOrId The string representing the chain alias (i.e. "mainnet") or a numerical ID (i.e. "1").
+ /// @return The numerical chain ID.
+ /// @dev It first attempts to parse the input as a number. If that fails, it uses `vm.getChain` to resolve a named alias.
+ /// Reverts if the alias is not valid or not a number.
+ function resolveChainId(string memory aliasOrId) public view returns (uint256) {
+ try vm.parseUint(aliasOrId) returns (uint256 chainId) {
+ return chainId;
+ } catch {
+ try vm.getChain(aliasOrId) returns (VmSafe.Chain memory chainInfo) {
+ return chainInfo.chainId;
+ } catch {
+ revert InvalidChainKey(aliasOrId);
+ }
+ }
+ }
+
+ /// @dev Retrieves the chain key/alias from the configuration based on the chain ID.
+ function _getChainKeyFromId(uint256 chainId) private view returns (string memory) {
+ for (uint256 i = 0; i < _chainKeys.length; i++) {
+ if (resolveChainId(_chainKeys[i]) == chainId) {
+ return _chainKeys[i];
+ }
+ }
+ revert ChainNotInitialized(chainId);
+ }
+
+ /// @dev Ensures type consistency when setting a value - prevents changing types unless uninitialized.
+ /// Updates type only when the previous type was `None`.
+ function _ensureTypeConsistency(uint256 chainId, string memory key, Type memory ty) private {
+ Type memory current = _typeOf[chainId][key];
+
+ if (current.kind == TypeKind.None) {
+ _typeOf[chainId][key] = ty;
+ } else {
+ current.assertEq(ty);
+ }
+ }
+
+ /// @dev Wraps a string in double quotes for JSON compatibility.
+ function _quote(string memory s) private pure returns (string memory) {
+ return string.concat('"', s, '"');
+ }
+
+ /// @dev Writes a JSON-formatted value to a specific key in the TOML file.
+ /// @param chainId The chain id to write under.
+ /// @param ty The type category ('bool', 'address', 'uint', 'bytes32', 'string', or 'bytes').
+ /// @param key The variable key name.
+ /// @param jsonValue The JSON-formatted value to write.
+ function _writeToToml(uint256 chainId, string memory ty, string memory key, string memory jsonValue) private {
+ string memory chainKey = _getChainKeyFromId(chainId);
+ string memory valueKey = string.concat("$.", chainKey, ".", ty, ".", key);
+ vm.writeToml(jsonValue, _filePath, valueKey);
+ }
+
+ // -- GETTER FUNCTIONS -----------------------------------------------------
+
+ /// @dev Reads a variable for a given chain id and key, and returns it in a generic container.
+ /// The caller should use `LibVariable` to safely coerce the type.
+ /// Example: `uint256 myVar = config.get("my_key").toUint256();`
+ ///
+ /// @param chain_id The chain ID to read from.
+ /// @param key The key of the variable to retrieve.
+ /// @return `Variable` struct containing the type and the ABI-encoded value.
+ function get(uint256 chain_id, string memory key) public view returns (Variable memory) {
+ return Variable(_typeOf[chain_id][key], _dataOf[chain_id][key]);
+ }
+
+ /// @dev Reads a variable for the current chain and a given key, and returns it in a generic container.
+ /// The caller should use `LibVariable` to safely coerce the type.
+ /// Example: `uint256 myVar = config.get("my_key").toUint256();`
+ ///
+ /// @param key The key of the variable to retrieve.
+ /// @return `Variable` struct containing the type and the ABI-encoded value.
+ function get(string memory key) public view returns (Variable memory) {
+ return get(vm.getChainId(), key);
+ }
+
+ /// @notice Returns the numerical chain ids for all configured chains.
+ function getChainIds() public view returns (uint256[] memory) {
+ string[] memory keys = _chainKeys;
+
+ uint256[] memory ids = new uint256[](keys.length);
+ for (uint256 i = 0; i < keys.length; i++) {
+ ids[i] = resolveChainId(keys[i]);
+ }
+
+ return ids;
+ }
+
+ /// @notice Reads the RPC URL for a specific chain id.
+ function getRpcUrl(uint256 chainId) public view returns (string memory) {
+ return _rpcOf[chainId];
+ }
+
+ /// @notice Reads the RPC URL for the current chain.
+ function getRpcUrl() public view returns (string memory) {
+ return _rpcOf[vm.getChainId()];
+ }
+
+ // -- SETTER FUNCTIONS (SINGLE VALUES) -------------------------------------
+
+ /// @notice Sets a boolean value for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, bool value) public {
+ Type memory ty = Type(TypeKind.Bool, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, vm.toString(value));
+ }
+
+ /// @notice Sets a boolean value for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, bool value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets an address value for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, address value) public {
+ Type memory ty = Type(TypeKind.Address, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, _quote(vm.toString(value)));
+ }
+
+ /// @notice Sets an address value for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, address value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a bytes32 value for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, bytes32 value) public {
+ Type memory ty = Type(TypeKind.Bytes32, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, _quote(vm.toString(value)));
+ }
+
+ /// @notice Sets a bytes32 value for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, bytes32 value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a uint256 value for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, uint256 value) public {
+ Type memory ty = Type(TypeKind.Uint256, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, vm.toString(value));
+ }
+
+ /// @notice Sets a uint256 value for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, uint256 value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets an int256 value for a given key and chain ID.
+ function set(uint256 chainId, string memory key, int256 value) public {
+ Type memory ty = Type(TypeKind.Int256, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, vm.toString(value));
+ }
+
+ /// @notice Sets an int256 value for a given key on the current chain.
+ function set(string memory key, int256 value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a string value for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, string memory value) public {
+ Type memory ty = Type(TypeKind.String, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, _quote(value));
+ }
+
+ /// @notice Sets a string value for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, string memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a bytes value for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, bytes memory value) public {
+ Type memory ty = Type(TypeKind.Bytes, false);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) _writeToToml(chainId, ty.kind.toTomlKey(), key, _quote(vm.toString(value)));
+ }
+
+ /// @notice Sets a bytes value for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, bytes memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ // -- SETTER FUNCTIONS (ARRAYS) --------------------------------------------
+
+ /// @notice Sets a boolean array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, bool[] memory value) public {
+ Type memory ty = Type(TypeKind.Bool, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, vm.toString(value[i]));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets a boolean array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, bool[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets an address array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, address[] memory value) public {
+ Type memory ty = Type(TypeKind.Address, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, _quote(vm.toString(value[i])));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets an address array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, address[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a bytes32 array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, bytes32[] memory value) public {
+ Type memory ty = Type(TypeKind.Bytes32, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, _quote(vm.toString(value[i])));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets a bytes32 array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, bytes32[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a uint256 array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, uint256[] memory value) public {
+ Type memory ty = Type(TypeKind.Uint256, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, vm.toString(value[i]));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets a uint256 array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, uint256[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a int256 array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, int256[] memory value) public {
+ Type memory ty = Type(TypeKind.Int256, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, vm.toString(value[i]));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets a int256 array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, int256[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a string array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, string[] memory value) public {
+ Type memory ty = Type(TypeKind.String, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, _quote(value[i]));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets a string array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, string[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+
+ /// @notice Sets a bytes array for a given key and chain ID.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(uint256 chainId, string memory key, bytes[] memory value) public {
+ Type memory ty = Type(TypeKind.Bytes, true);
+ _ensureTypeConsistency(chainId, key, ty);
+ _dataOf[chainId][key] = abi.encode(value);
+ if (_writeToFile) {
+ string memory json = "[";
+ for (uint256 i = 0; i < value.length; i++) {
+ json = string.concat(json, _quote(vm.toString(value[i])));
+ if (i < value.length - 1) json = string.concat(json, ",");
+ }
+ json = string.concat(json, "]");
+ _writeToToml(chainId, ty.kind.toTomlKey(), key, json);
+ }
+ }
+
+ /// @notice Sets a bytes array for a given key on the current chain.
+ /// @dev Sets the cached value in storage and writes the change back to the TOML file if `autoWrite` is enabled.
+ function set(string memory key, bytes[] memory value) public {
+ set(vm.getChainId(), key, value);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdConstants.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdConstants.sol
new file mode 100644
index 000000000..2047d2b33
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdConstants.sol
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {IMulticall3} from "./interfaces/IMulticall3.sol";
+import {Vm} from "./Vm.sol";
+
+library StdConstants {
+ /// @dev Cheat code address.
+ /// Calculated as `address(uint160(uint256(keccak256("hevm cheat code"))))`.
+ Vm internal constant VM = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
+ /// @dev console.sol and console2.sol work by executing a staticcall to this address.
+ /// Calculated as `address(uint160(uint88(bytes11("console.log"))))`.
+ address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
+ /// @dev Used when deploying with create2.
+ /// Taken from https://github.com/Arachnid/deterministic-deployment-proxy.
+ address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+ /// @dev The default address for tx.origin and msg.sender.
+ /// Calculated as `address(uint160(uint256(keccak256("foundry default caller"))))`.
+ address internal constant DEFAULT_SENDER = 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
+ /// @dev The address of the first contract `CREATE`d by a running test contract.
+ /// When running tests, each test contract is `CREATE`d by `DEFAULT_SENDER` with nonce 1.
+ /// Calculated as `VM.computeCreateAddress(VM.computeCreateAddress(DEFAULT_SENDER, 1), 1)`.
+ address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
+ /// @dev Deterministic deployment address of the Multicall3 contract.
+ /// Taken from https://www.multicall3.com.
+ IMulticall3 internal constant MULTICALL3_ADDRESS = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
+ /// @dev The order of the secp256k1 curve.
+ uint256 internal constant SECP256K1_ORDER =
+ 115792089237316195423570985008687907852837564279074904382605163141518161494337;
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdError.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdError.sol
new file mode 100644
index 000000000..a302191fa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdError.sol
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: MIT
+// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test
+pragma solidity >=0.6.2 <0.9.0;
+
+library stdError {
+ bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
+ bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);
+ bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12);
+ bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21);
+ bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22);
+ bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31);
+ bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32);
+ bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41);
+ bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdInvariant.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdInvariant.sol
new file mode 100644
index 000000000..056db98fc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdInvariant.sol
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+abstract contract StdInvariant {
+ struct FuzzSelector {
+ address addr;
+ bytes4[] selectors;
+ }
+
+ struct FuzzArtifactSelector {
+ string artifact;
+ bytes4[] selectors;
+ }
+
+ struct FuzzInterface {
+ address addr;
+ string[] artifacts;
+ }
+
+ address[] private _excludedContracts;
+ address[] private _excludedSenders;
+ address[] private _targetedContracts;
+ address[] private _targetedSenders;
+
+ string[] private _excludedArtifacts;
+ string[] private _targetedArtifacts;
+
+ FuzzArtifactSelector[] private _targetedArtifactSelectors;
+
+ FuzzSelector[] private _excludedSelectors;
+ FuzzSelector[] private _targetedSelectors;
+
+ FuzzInterface[] private _targetedInterfaces;
+
+ // Functions for users:
+ // These are intended to be called in tests.
+
+ function excludeContract(address newExcludedContract_) internal {
+ _excludedContracts.push(newExcludedContract_);
+ }
+
+ function excludeSelector(FuzzSelector memory newExcludedSelector_) internal {
+ _excludedSelectors.push(newExcludedSelector_);
+ }
+
+ function excludeSender(address newExcludedSender_) internal {
+ _excludedSenders.push(newExcludedSender_);
+ }
+
+ function excludeArtifact(string memory newExcludedArtifact_) internal {
+ _excludedArtifacts.push(newExcludedArtifact_);
+ }
+
+ function targetArtifact(string memory newTargetedArtifact_) internal {
+ _targetedArtifacts.push(newTargetedArtifact_);
+ }
+
+ function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal {
+ _targetedArtifactSelectors.push(newTargetedArtifactSelector_);
+ }
+
+ function targetContract(address newTargetedContract_) internal {
+ _targetedContracts.push(newTargetedContract_);
+ }
+
+ function targetSelector(FuzzSelector memory newTargetedSelector_) internal {
+ _targetedSelectors.push(newTargetedSelector_);
+ }
+
+ function targetSender(address newTargetedSender_) internal {
+ _targetedSenders.push(newTargetedSender_);
+ }
+
+ function targetInterface(FuzzInterface memory newTargetedInterface_) internal {
+ _targetedInterfaces.push(newTargetedInterface_);
+ }
+
+ // Functions for forge:
+ // These are called by forge to run invariant tests and don't need to be called in tests.
+
+ function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {
+ excludedArtifacts_ = _excludedArtifacts;
+ }
+
+ function excludeContracts() public view returns (address[] memory excludedContracts_) {
+ excludedContracts_ = _excludedContracts;
+ }
+
+ function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) {
+ excludedSelectors_ = _excludedSelectors;
+ }
+
+ function excludeSenders() public view returns (address[] memory excludedSenders_) {
+ excludedSenders_ = _excludedSenders;
+ }
+
+ function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {
+ targetedArtifacts_ = _targetedArtifacts;
+ }
+
+ function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) {
+ targetedArtifactSelectors_ = _targetedArtifactSelectors;
+ }
+
+ function targetContracts() public view returns (address[] memory targetedContracts_) {
+ targetedContracts_ = _targetedContracts;
+ }
+
+ function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {
+ targetedSelectors_ = _targetedSelectors;
+ }
+
+ function targetSenders() public view returns (address[] memory targetedSenders_) {
+ targetedSenders_ = _targetedSenders;
+ }
+
+ function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) {
+ targetedInterfaces_ = _targetedInterfaces;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdJson.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdJson.sol
new file mode 100644
index 000000000..2a033c03a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdJson.sol
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.0 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {VmSafe} from "./Vm.sol";
+
+// Helpers for parsing and writing JSON files
+// To parse:
+// ```
+// using stdJson for string;
+// string memory json = vm.readFile("");
+// json.readUint("");
+// ```
+// To write:
+// ```
+// using stdJson for string;
+// string memory json = "json";
+// json.serialize("a", uint256(123));
+// string memory semiFinal = json.serialize("b", string("test"));
+// string memory finalJson = json.serialize("c", semiFinal);
+// finalJson.write("");
+// ```
+
+library stdJson {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function keyExists(string memory json, string memory key) internal view returns (bool) {
+ return vm.keyExistsJson(json, key);
+ }
+
+ function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
+ return vm.parseJson(json, key);
+ }
+
+ function readUint(string memory json, string memory key) internal pure returns (uint256) {
+ return vm.parseJsonUint(json, key);
+ }
+
+ function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
+ return vm.parseJsonUintArray(json, key);
+ }
+
+ function readInt(string memory json, string memory key) internal pure returns (int256) {
+ return vm.parseJsonInt(json, key);
+ }
+
+ function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
+ return vm.parseJsonIntArray(json, key);
+ }
+
+ function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
+ return vm.parseJsonBytes32(json, key);
+ }
+
+ function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
+ return vm.parseJsonBytes32Array(json, key);
+ }
+
+ function readString(string memory json, string memory key) internal pure returns (string memory) {
+ return vm.parseJsonString(json, key);
+ }
+
+ function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
+ return vm.parseJsonStringArray(json, key);
+ }
+
+ function readAddress(string memory json, string memory key) internal pure returns (address) {
+ return vm.parseJsonAddress(json, key);
+ }
+
+ function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
+ return vm.parseJsonAddressArray(json, key);
+ }
+
+ function readBool(string memory json, string memory key) internal pure returns (bool) {
+ return vm.parseJsonBool(json, key);
+ }
+
+ function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
+ return vm.parseJsonBoolArray(json, key);
+ }
+
+ function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
+ return vm.parseJsonBytes(json, key);
+ }
+
+ function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
+ return vm.parseJsonBytesArray(json, key);
+ }
+
+ function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) {
+ return keyExists(json, key) ? readUint(json, key) : defaultValue;
+ }
+
+ function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue)
+ internal
+ view
+ returns (uint256[] memory)
+ {
+ return keyExists(json, key) ? readUintArray(json, key) : defaultValue;
+ }
+
+ function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) {
+ return keyExists(json, key) ? readInt(json, key) : defaultValue;
+ }
+
+ function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue)
+ internal
+ view
+ returns (int256[] memory)
+ {
+ return keyExists(json, key) ? readIntArray(json, key) : defaultValue;
+ }
+
+ function readBytes32Or(string memory json, string memory key, bytes32 defaultValue)
+ internal
+ view
+ returns (bytes32)
+ {
+ return keyExists(json, key) ? readBytes32(json, key) : defaultValue;
+ }
+
+ function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue)
+ internal
+ view
+ returns (bytes32[] memory)
+ {
+ return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue;
+ }
+
+ function readStringOr(string memory json, string memory key, string memory defaultValue)
+ internal
+ view
+ returns (string memory)
+ {
+ return keyExists(json, key) ? readString(json, key) : defaultValue;
+ }
+
+ function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue)
+ internal
+ view
+ returns (string[] memory)
+ {
+ return keyExists(json, key) ? readStringArray(json, key) : defaultValue;
+ }
+
+ function readAddressOr(string memory json, string memory key, address defaultValue)
+ internal
+ view
+ returns (address)
+ {
+ return keyExists(json, key) ? readAddress(json, key) : defaultValue;
+ }
+
+ function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue)
+ internal
+ view
+ returns (address[] memory)
+ {
+ return keyExists(json, key) ? readAddressArray(json, key) : defaultValue;
+ }
+
+ function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) {
+ return keyExists(json, key) ? readBool(json, key) : defaultValue;
+ }
+
+ function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue)
+ internal
+ view
+ returns (bool[] memory)
+ {
+ return keyExists(json, key) ? readBoolArray(json, key) : defaultValue;
+ }
+
+ function readBytesOr(string memory json, string memory key, bytes memory defaultValue)
+ internal
+ view
+ returns (bytes memory)
+ {
+ return keyExists(json, key) ? readBytes(json, key) : defaultValue;
+ }
+
+ function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue)
+ internal
+ view
+ returns (bytes[] memory)
+ {
+ return keyExists(json, key) ? readBytesArray(json, key) : defaultValue;
+ }
+
+ function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
+ return vm.serializeJson(jsonKey, rootObject);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function write(string memory jsonKey, string memory path) internal {
+ vm.writeJson(jsonKey, path);
+ }
+
+ function write(string memory jsonKey, string memory path, string memory valueKey) internal {
+ vm.writeJson(jsonKey, path, valueKey);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdMath.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdMath.sol
new file mode 100644
index 000000000..459523bda
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdMath.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+library stdMath {
+ int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;
+
+ function abs(int256 a) internal pure returns (uint256) {
+ // Required or it will fail when `a = type(int256).min`
+ if (a == INT256_MIN) {
+ return 57896044618658097711785492504343953926634992332820282019728792003956564819968;
+ }
+
+ return uint256(a > 0 ? a : -a);
+ }
+
+ function delta(uint256 a, uint256 b) internal pure returns (uint256) {
+ return a > b ? a - b : b - a;
+ }
+
+ function delta(int256 a, int256 b) internal pure returns (uint256) {
+ // a and b are of the same sign
+ // this works thanks to two's complement, the left-most bit is the sign bit
+ if ((a ^ b) > -1) {
+ return delta(abs(a), abs(b));
+ }
+
+ // a and b are of opposite signs
+ return abs(a) + abs(b);
+ }
+
+ function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
+ uint256 absDelta = delta(a, b);
+
+ return absDelta * 1e18 / b;
+ }
+
+ function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
+ uint256 absDelta = delta(a, b);
+ uint256 absB = abs(b);
+
+ return absDelta * 1e18 / absB;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdStorage.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdStorage.sol
new file mode 100644
index 000000000..1627af753
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdStorage.sol
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {Vm} from "./Vm.sol";
+
+struct FindData {
+ uint256 slot;
+ uint256 offsetLeft;
+ uint256 offsetRight;
+ bool found;
+}
+
+struct StdStorage {
+ mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds;
+ bytes32[] _keys;
+ bytes4 _sig;
+ uint256 _depth;
+ address _target;
+ bytes32 _set;
+ bool _enable_packed_slots;
+ bytes _calldata;
+}
+
+library stdStorageSafe {
+ event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
+ event WARNING_UninitedSlot(address who, uint256 slot);
+
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+ uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ function sigs(string memory sigStr) internal pure returns (bytes4) {
+ return bytes4(keccak256(bytes(sigStr)));
+ }
+
+ function getCallParams(StdStorage storage self) internal view returns (bytes memory) {
+ if (self._calldata.length == 0) {
+ return flatten(self._keys);
+ } else {
+ return self._calldata;
+ }
+ }
+
+ // Calls target contract with configured parameters
+ function callTarget(StdStorage storage self) internal view returns (bool, bytes32) {
+ bytes memory cd = abi.encodePacked(self._sig, getCallParams(self));
+ (bool success, bytes memory rdat) = self._target.staticcall(cd);
+ bytes32 result = bytesToBytes32(rdat, 32 * self._depth);
+
+ return (success, result);
+ }
+
+ // Tries mutating slot value to determine if the targeted value is stored in it.
+ // If current value is 0, then we are setting slot value to type(uint256).max
+ // Otherwise, we set it to 0. That way, return value should always be affected.
+ function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) {
+ bytes32 prevSlotValue = vm.load(self._target, slot);
+ (bool success, bytes32 prevReturnValue) = callTarget(self);
+
+ bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0);
+ vm.store(self._target, slot, testVal);
+
+ (, bytes32 newReturnValue) = callTarget(self);
+
+ vm.store(self._target, slot, prevSlotValue);
+
+ return (success && (prevReturnValue != newReturnValue));
+ }
+
+ // Tries setting one of the bits in slot to 1 until return value changes.
+ // Index of resulted bit is an offset packed slot has from left/right side
+ function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) {
+ for (uint256 offset = 0; offset < 256; offset++) {
+ uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset);
+ vm.store(self._target, slot, bytes32(valueToPut));
+
+ (bool success, bytes32 data) = callTarget(self);
+
+ if (success && (uint256(data) > 0)) {
+ return (true, offset);
+ }
+ }
+ return (false, 0);
+ }
+
+ function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) {
+ bytes32 prevSlotValue = vm.load(self._target, slot);
+
+ (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true);
+ (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false);
+
+ // `findOffset` may mutate slot value, so we are setting it to initial value
+ vm.store(self._target, slot, prevSlotValue);
+ return (foundLeft && foundRight, offsetLeft, offsetRight);
+ }
+
+ function find(StdStorage storage self) internal returns (FindData storage) {
+ return find(self, true);
+ }
+
+ /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
+ // slot complexity:
+ // if flat, will be bytes32(uint256(uint));
+ // if map, will be keccak256(abi.encode(key, uint(slot)));
+ // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
+ // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
+ function find(StdStorage storage self, bool _clear) internal returns (FindData storage) {
+ address who = self._target;
+ bytes4 fsig = self._sig;
+ uint256 field_depth = self._depth;
+ bytes memory params = getCallParams(self);
+
+ // calldata to test against
+ if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
+ if (_clear) {
+ clear(self);
+ }
+ return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
+ }
+ vm.record();
+ (, bytes32 callResult) = callTarget(self);
+ (bytes32[] memory reads,) = vm.accesses(address(who));
+
+ if (reads.length == 0) {
+ revert("stdStorage find(StdStorage): No storage use detected for target.");
+ } else {
+ for (uint256 i = reads.length; --i >= 0;) {
+ bytes32 prev = vm.load(who, reads[i]);
+ if (prev == bytes32(0)) {
+ emit WARNING_UninitedSlot(who, uint256(reads[i]));
+ }
+
+ if (!checkSlotMutatesCall(self, reads[i])) {
+ continue;
+ }
+
+ (uint256 offsetLeft, uint256 offsetRight) = (0, 0);
+
+ if (self._enable_packed_slots) {
+ bool found;
+ (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]);
+ if (!found) {
+ continue;
+ }
+ }
+
+ // Check that value between found offsets is equal to the current call result
+ uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight;
+
+ if (uint256(callResult) != curVal) {
+ continue;
+ }
+
+ emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i]));
+ self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] =
+ FindData(uint256(reads[i]), offsetLeft, offsetRight, true);
+ break;
+ }
+ }
+
+ require(
+ self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found,
+ "stdStorage find(StdStorage): Slot(s) not found."
+ );
+
+ if (_clear) {
+ clear(self);
+ }
+ return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
+ }
+
+ function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
+ self._target = _target;
+ return self;
+ }
+
+ function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
+ self._sig = _sig;
+ return self;
+ }
+
+ function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
+ self._sig = sigs(_sig);
+ return self;
+ }
+
+ function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
+ self._calldata = _calldata;
+ return self;
+ }
+
+ function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
+ self._keys.push(bytes32(uint256(uint160(who))));
+ return self;
+ }
+
+ function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
+ self._keys.push(bytes32(amt));
+ return self;
+ }
+
+ function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
+ self._keys.push(key);
+ return self;
+ }
+
+ function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
+ self._enable_packed_slots = true;
+ return self;
+ }
+
+ function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
+ self._depth = _depth;
+ return self;
+ }
+
+ function read(StdStorage storage self) private returns (bytes memory) {
+ FindData storage data = find(self, false);
+ uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight);
+ uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight;
+ clear(self);
+ return abi.encode(value);
+ }
+
+ function read_bytes32(StdStorage storage self) internal returns (bytes32) {
+ return abi.decode(read(self), (bytes32));
+ }
+
+ function read_bool(StdStorage storage self) internal returns (bool) {
+ int256 v = read_int(self);
+ if (v == 0) return false;
+ if (v == 1) return true;
+ revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
+ }
+
+ function read_address(StdStorage storage self) internal returns (address) {
+ return abi.decode(read(self), (address));
+ }
+
+ function read_uint(StdStorage storage self) internal returns (uint256) {
+ return abi.decode(read(self), (uint256));
+ }
+
+ function read_int(StdStorage storage self) internal returns (int256) {
+ return abi.decode(read(self), (int256));
+ }
+
+ function parent(StdStorage storage self) internal returns (uint256, bytes32) {
+ address who = self._target;
+ uint256 field_depth = self._depth;
+ vm.startMappingRecording();
+ uint256 child = find(self, true).slot - field_depth;
+ (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
+ if (!found) {
+ revert(
+ "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
+ );
+ }
+ return (uint256(parent_slot), key);
+ }
+
+ function root(StdStorage storage self) internal returns (uint256) {
+ address who = self._target;
+ uint256 field_depth = self._depth;
+ vm.startMappingRecording();
+ uint256 child = find(self, true).slot - field_depth;
+ bool found;
+ bytes32 root_slot;
+ bytes32 parent_slot;
+ (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
+ if (!found) {
+ revert(
+ "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
+ );
+ }
+ while (found) {
+ root_slot = parent_slot;
+ (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
+ }
+ return uint256(root_slot);
+ }
+
+ function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
+ bytes32 out;
+
+ uint256 max = b.length > 32 ? 32 : b.length;
+ for (uint256 i = 0; i < max; i++) {
+ out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
+ }
+ return out;
+ }
+
+ function flatten(bytes32[] memory b) private pure returns (bytes memory) {
+ bytes memory result = new bytes(b.length * 32);
+ for (uint256 i = 0; i < b.length; i++) {
+ bytes32 k = b[i];
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(add(result, add(32, mul(32, i))), k)
+ }
+ }
+
+ return result;
+ }
+
+ function clear(StdStorage storage self) internal {
+ delete self._target;
+ delete self._sig;
+ delete self._keys;
+ delete self._depth;
+ delete self._enable_packed_slots;
+ delete self._calldata;
+ }
+
+ // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight`
+ // (slotValue & mask) >> offsetRight will be the value of the given packed variable
+ function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) {
+ // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight;
+ // using assembly because (1 << 256) causes overflow
+ assembly {
+ mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1))
+ }
+ }
+
+ // Returns slot value with updated packed variable.
+ function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight)
+ internal
+ pure
+ returns (bytes32 newValue)
+ {
+ return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight));
+ }
+}
+
+library stdStorage {
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function sigs(string memory sigStr) internal pure returns (bytes4) {
+ return stdStorageSafe.sigs(sigStr);
+ }
+
+ function find(StdStorage storage self) internal returns (uint256) {
+ return find(self, true);
+ }
+
+ function find(StdStorage storage self, bool _clear) internal returns (uint256) {
+ return stdStorageSafe.find(self, _clear).slot;
+ }
+
+ function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
+ return stdStorageSafe.target(self, _target);
+ }
+
+ function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
+ return stdStorageSafe.sig(self, _sig);
+ }
+
+ function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
+ return stdStorageSafe.sig(self, _sig);
+ }
+
+ function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_key(self, who);
+ }
+
+ function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_key(self, amt);
+ }
+
+ function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_key(self, key);
+ }
+
+ function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_calldata(self, _calldata);
+ }
+
+ function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
+ return stdStorageSafe.enable_packed_slots(self);
+ }
+
+ function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
+ return stdStorageSafe.depth(self, _depth);
+ }
+
+ function clear(StdStorage storage self) internal {
+ stdStorageSafe.clear(self);
+ }
+
+ function checked_write(StdStorage storage self, address who) internal {
+ checked_write(self, bytes32(uint256(uint160(who))));
+ }
+
+ function checked_write(StdStorage storage self, uint256 amt) internal {
+ checked_write(self, bytes32(amt));
+ }
+
+ function checked_write_int(StdStorage storage self, int256 val) internal {
+ checked_write(self, bytes32(uint256(val)));
+ }
+
+ function checked_write(StdStorage storage self, bool write) internal {
+ bytes32 t;
+ /// @solidity memory-safe-assembly
+ assembly {
+ t := write
+ }
+ checked_write(self, t);
+ }
+
+ function checked_write(StdStorage storage self, bytes32 set) internal {
+ address who = self._target;
+ bytes4 fsig = self._sig;
+ uint256 field_depth = self._depth;
+ bytes memory params = stdStorageSafe.getCallParams(self);
+
+ if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
+ find(self, false);
+ }
+ FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
+ if ((data.offsetLeft + data.offsetRight) > 0) {
+ uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight));
+ require(
+ uint256(set) < maxVal,
+ string(
+ abi.encodePacked(
+ "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ",
+ vm.toString(maxVal)
+ )
+ )
+ );
+ }
+ bytes32 curVal = vm.load(who, bytes32(data.slot));
+ bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight);
+
+ vm.store(who, bytes32(data.slot), valToSet);
+
+ (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self);
+
+ if (!success || callResult != set) {
+ vm.store(who, bytes32(data.slot), curVal);
+ revert("stdStorage find(StdStorage): Failed to write value.");
+ }
+ clear(self);
+ }
+
+ function read_bytes32(StdStorage storage self) internal returns (bytes32) {
+ return stdStorageSafe.read_bytes32(self);
+ }
+
+ function read_bool(StdStorage storage self) internal returns (bool) {
+ return stdStorageSafe.read_bool(self);
+ }
+
+ function read_address(StdStorage storage self) internal returns (address) {
+ return stdStorageSafe.read_address(self);
+ }
+
+ function read_uint(StdStorage storage self) internal returns (uint256) {
+ return stdStorageSafe.read_uint(self);
+ }
+
+ function read_int(StdStorage storage self) internal returns (int256) {
+ return stdStorageSafe.read_int(self);
+ }
+
+ function parent(StdStorage storage self) internal returns (uint256, bytes32) {
+ return stdStorageSafe.parent(self);
+ }
+
+ function root(StdStorage storage self) internal returns (uint256) {
+ return stdStorageSafe.root(self);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdStyle.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdStyle.sol
new file mode 100644
index 000000000..d371e0c60
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdStyle.sol
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.4.22 <0.9.0;
+
+import {VmSafe} from "./Vm.sol";
+
+library StdStyle {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ string constant RED = "\u001b[91m";
+ string constant GREEN = "\u001b[92m";
+ string constant YELLOW = "\u001b[93m";
+ string constant BLUE = "\u001b[94m";
+ string constant MAGENTA = "\u001b[95m";
+ string constant CYAN = "\u001b[96m";
+ string constant BOLD = "\u001b[1m";
+ string constant DIM = "\u001b[2m";
+ string constant ITALIC = "\u001b[3m";
+ string constant UNDERLINE = "\u001b[4m";
+ string constant INVERSE = "\u001b[7m";
+ string constant RESET = "\u001b[0m";
+
+ function styleConcat(string memory style, string memory self) private pure returns (string memory) {
+ return string(abi.encodePacked(style, self, RESET));
+ }
+
+ function red(string memory self) internal pure returns (string memory) {
+ return styleConcat(RED, self);
+ }
+
+ function red(uint256 self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function red(int256 self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function red(address self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function red(bool self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function redBytes(bytes memory self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function redBytes32(bytes32 self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function green(string memory self) internal pure returns (string memory) {
+ return styleConcat(GREEN, self);
+ }
+
+ function green(uint256 self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function green(int256 self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function green(address self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function green(bool self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function greenBytes(bytes memory self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function greenBytes32(bytes32 self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function yellow(string memory self) internal pure returns (string memory) {
+ return styleConcat(YELLOW, self);
+ }
+
+ function yellow(uint256 self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellow(int256 self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellow(address self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellow(bool self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellowBytes(bytes memory self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellowBytes32(bytes32 self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function blue(string memory self) internal pure returns (string memory) {
+ return styleConcat(BLUE, self);
+ }
+
+ function blue(uint256 self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blue(int256 self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blue(address self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blue(bool self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blueBytes(bytes memory self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blueBytes32(bytes32 self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function magenta(string memory self) internal pure returns (string memory) {
+ return styleConcat(MAGENTA, self);
+ }
+
+ function magenta(uint256 self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magenta(int256 self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magenta(address self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magenta(bool self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magentaBytes(bytes memory self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magentaBytes32(bytes32 self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function cyan(string memory self) internal pure returns (string memory) {
+ return styleConcat(CYAN, self);
+ }
+
+ function cyan(uint256 self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyan(int256 self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyan(address self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyan(bool self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyanBytes(bytes memory self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyanBytes32(bytes32 self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function bold(string memory self) internal pure returns (string memory) {
+ return styleConcat(BOLD, self);
+ }
+
+ function bold(uint256 self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function bold(int256 self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function bold(address self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function bold(bool self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function boldBytes(bytes memory self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function boldBytes32(bytes32 self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function dim(string memory self) internal pure returns (string memory) {
+ return styleConcat(DIM, self);
+ }
+
+ function dim(uint256 self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dim(int256 self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dim(address self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dim(bool self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dimBytes(bytes memory self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dimBytes32(bytes32 self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function italic(string memory self) internal pure returns (string memory) {
+ return styleConcat(ITALIC, self);
+ }
+
+ function italic(uint256 self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italic(int256 self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italic(address self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italic(bool self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italicBytes(bytes memory self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italicBytes32(bytes32 self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function underline(string memory self) internal pure returns (string memory) {
+ return styleConcat(UNDERLINE, self);
+ }
+
+ function underline(uint256 self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underline(int256 self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underline(address self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underline(bool self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underlineBytes(bytes memory self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underlineBytes32(bytes32 self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function inverse(string memory self) internal pure returns (string memory) {
+ return styleConcat(INVERSE, self);
+ }
+
+ function inverse(uint256 self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverse(int256 self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverse(address self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverse(bool self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverseBytes(bytes memory self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverseBytes32(bytes32 self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdToml.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdToml.sol
new file mode 100644
index 000000000..7ad3be2f9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdToml.sol
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.0 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {VmSafe} from "./Vm.sol";
+
+// Helpers for parsing and writing TOML files
+// To parse:
+// ```
+// using stdToml for string;
+// string memory toml = vm.readFile("");
+// toml.readUint("");
+// ```
+// To write:
+// ```
+// using stdToml for string;
+// string memory json = "json";
+// json.serialize("a", uint256(123));
+// string memory semiFinal = json.serialize("b", string("test"));
+// string memory finalJson = json.serialize("c", semiFinal);
+// finalJson.write("");
+// ```
+
+library stdToml {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function keyExists(string memory toml, string memory key) internal view returns (bool) {
+ return vm.keyExistsToml(toml, key);
+ }
+
+ function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) {
+ return vm.parseToml(toml, key);
+ }
+
+ function readUint(string memory toml, string memory key) internal pure returns (uint256) {
+ return vm.parseTomlUint(toml, key);
+ }
+
+ function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) {
+ return vm.parseTomlUintArray(toml, key);
+ }
+
+ function readInt(string memory toml, string memory key) internal pure returns (int256) {
+ return vm.parseTomlInt(toml, key);
+ }
+
+ function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) {
+ return vm.parseTomlIntArray(toml, key);
+ }
+
+ function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) {
+ return vm.parseTomlBytes32(toml, key);
+ }
+
+ function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) {
+ return vm.parseTomlBytes32Array(toml, key);
+ }
+
+ function readString(string memory toml, string memory key) internal pure returns (string memory) {
+ return vm.parseTomlString(toml, key);
+ }
+
+ function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) {
+ return vm.parseTomlStringArray(toml, key);
+ }
+
+ function readAddress(string memory toml, string memory key) internal pure returns (address) {
+ return vm.parseTomlAddress(toml, key);
+ }
+
+ function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) {
+ return vm.parseTomlAddressArray(toml, key);
+ }
+
+ function readBool(string memory toml, string memory key) internal pure returns (bool) {
+ return vm.parseTomlBool(toml, key);
+ }
+
+ function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) {
+ return vm.parseTomlBoolArray(toml, key);
+ }
+
+ function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) {
+ return vm.parseTomlBytes(toml, key);
+ }
+
+ function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) {
+ return vm.parseTomlBytesArray(toml, key);
+ }
+
+ function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) {
+ return keyExists(toml, key) ? readUint(toml, key) : defaultValue;
+ }
+
+ function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue)
+ internal
+ view
+ returns (uint256[] memory)
+ {
+ return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue;
+ }
+
+ function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) {
+ return keyExists(toml, key) ? readInt(toml, key) : defaultValue;
+ }
+
+ function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue)
+ internal
+ view
+ returns (int256[] memory)
+ {
+ return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue;
+ }
+
+ function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue)
+ internal
+ view
+ returns (bytes32)
+ {
+ return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue;
+ }
+
+ function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue)
+ internal
+ view
+ returns (bytes32[] memory)
+ {
+ return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue;
+ }
+
+ function readStringOr(string memory toml, string memory key, string memory defaultValue)
+ internal
+ view
+ returns (string memory)
+ {
+ return keyExists(toml, key) ? readString(toml, key) : defaultValue;
+ }
+
+ function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue)
+ internal
+ view
+ returns (string[] memory)
+ {
+ return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue;
+ }
+
+ function readAddressOr(string memory toml, string memory key, address defaultValue)
+ internal
+ view
+ returns (address)
+ {
+ return keyExists(toml, key) ? readAddress(toml, key) : defaultValue;
+ }
+
+ function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue)
+ internal
+ view
+ returns (address[] memory)
+ {
+ return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue;
+ }
+
+ function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) {
+ return keyExists(toml, key) ? readBool(toml, key) : defaultValue;
+ }
+
+ function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue)
+ internal
+ view
+ returns (bool[] memory)
+ {
+ return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue;
+ }
+
+ function readBytesOr(string memory toml, string memory key, bytes memory defaultValue)
+ internal
+ view
+ returns (bytes memory)
+ {
+ return keyExists(toml, key) ? readBytes(toml, key) : defaultValue;
+ }
+
+ function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue)
+ internal
+ view
+ returns (bytes[] memory)
+ {
+ return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue;
+ }
+
+ function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
+ return vm.serializeJson(jsonKey, rootObject);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function write(string memory jsonKey, string memory path) internal {
+ vm.writeToml(jsonKey, path);
+ }
+
+ function write(string memory jsonKey, string memory path, string memory valueKey) internal {
+ vm.writeToml(jsonKey, path, valueKey);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/StdUtils.sol b/lib/signals-implicit-mode/lib/forge-std/src/StdUtils.sol
new file mode 100644
index 000000000..9321df143
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/StdUtils.sol
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {IMulticall3} from "./interfaces/IMulticall3.sol";
+import {VmSafe} from "./Vm.sol";
+
+abstract contract StdUtils {
+ /*//////////////////////////////////////////////////////////////////////////
+ CONSTANTS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+ address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
+ uint256 private constant INT256_MIN_ABS =
+ 57896044618658097711785492504343953926634992332820282019728792003956564819968;
+ uint256 private constant SECP256K1_ORDER =
+ 115792089237316195423570985008687907852837564279074904382605163141518161494337;
+ uint256 private constant UINT256_MAX =
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
+ address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+
+ /*//////////////////////////////////////////////////////////////////////////
+ INTERNAL FUNCTIONS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
+ require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
+ // If x is between min and max, return x directly. This is to ensure that dictionary values
+ // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
+ if (x >= min && x <= max) return x;
+
+ uint256 size = max - min + 1;
+
+ // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
+ // This helps ensure coverage of the min/max values.
+ if (x <= 3 && size > x) return min + x;
+ if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
+
+ // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
+ if (x > max) {
+ uint256 diff = x - max;
+ uint256 rem = diff % size;
+ if (rem == 0) return max;
+ result = min + rem - 1;
+ } else if (x < min) {
+ uint256 diff = min - x;
+ uint256 rem = diff % size;
+ if (rem == 0) return min;
+ result = max - rem + 1;
+ }
+ }
+
+ function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
+ result = _bound(x, min, max);
+ console2_log_StdUtils("Bound result", result);
+ }
+
+ function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
+ require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
+
+ // Shifting all int256 values to uint256 to use _bound function. The range of two types are:
+ // int256 : -(2**255) ~ (2**255 - 1)
+ // uint256: 0 ~ (2**256 - 1)
+ // So, add 2**255, INT256_MIN_ABS to the integer values.
+ //
+ // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
+ // So, use `~uint256(x) + 1` instead.
+ uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
+ uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
+ uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
+
+ uint256 y = _bound(_x, _min, _max);
+
+ // To move it back to int256 value, subtract INT256_MIN_ABS at here.
+ result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
+ }
+
+ function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
+ result = _bound(x, min, max);
+ console2_log_StdUtils("Bound result", vm.toString(result));
+ }
+
+ function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
+ result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
+ }
+
+ function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
+ require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
+ return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
+ }
+
+ /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
+ function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
+ console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
+ return vm.computeCreateAddress(deployer, nonce);
+ }
+
+ function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
+ internal
+ pure
+ virtual
+ returns (address)
+ {
+ console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
+ return vm.computeCreate2Address(salt, initcodeHash, deployer);
+ }
+
+ /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
+ function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
+ console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
+ return vm.computeCreate2Address(salt, initCodeHash);
+ }
+
+ /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
+ /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
+ function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
+ return hashInitCode(creationCode, "");
+ }
+
+ /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
+ /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
+ /// @param args the ABI-encoded arguments to the constructor of C
+ function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(creationCode, args));
+ }
+
+ // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
+ function getTokenBalances(address token, address[] memory addresses)
+ internal
+ virtual
+ returns (uint256[] memory balances)
+ {
+ uint256 tokenCodeSize;
+ assembly {
+ tokenCodeSize := extcodesize(token)
+ }
+ require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
+
+ // ABI encode the aggregate call to Multicall3.
+ uint256 length = addresses.length;
+ IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
+ for (uint256 i = 0; i < length; ++i) {
+ // 0x70a08231 = bytes4("balanceOf(address)"))
+ calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
+ }
+
+ // Make the aggregate call.
+ (, bytes[] memory returnData) = multicall.aggregate(calls);
+
+ // ABI decode the return data and return the balances.
+ balances = new uint256[](length);
+ for (uint256 i = 0; i < length; ++i) {
+ balances[i] = abi.decode(returnData[i], (uint256));
+ }
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ PRIVATE FUNCTIONS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
+ return address(uint160(uint256(bytesValue)));
+ }
+
+ // This section is used to prevent the compilation of console, which shortens the compilation time when console is
+ // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
+ // any breaking changes to function signatures.
+ function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
+ internal
+ pure
+ returns (function(bytes memory) internal pure fnOut)
+ {
+ assembly {
+ fnOut := fnIn
+ }
+ }
+
+ function _sendLogPayload(bytes memory payload) internal pure {
+ _castLogPayloadViewToPure(_sendLogPayloadView)(payload);
+ }
+
+ function _sendLogPayloadView(bytes memory payload) private view {
+ uint256 payloadLength = payload.length;
+ address consoleAddress = CONSOLE2_ADDRESS;
+ /// @solidity memory-safe-assembly
+ assembly {
+ let payloadStart := add(payload, 32)
+ let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
+ }
+ }
+
+ function console2_log_StdUtils(string memory p0) private pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
+ }
+
+ function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
+ }
+
+ function console2_log_StdUtils(string memory p0, string memory p1) private pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/Test.sol b/lib/signals-implicit-mode/lib/forge-std/src/Test.sol
new file mode 100644
index 000000000..11b18f29f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/Test.sol
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+// 💬 ABOUT
+// Forge Std's default Test.
+
+// 🧩 MODULES
+import {console} from "./console.sol";
+import {console2} from "./console2.sol";
+import {safeconsole} from "./safeconsole.sol";
+import {StdAssertions} from "./StdAssertions.sol";
+import {StdChains} from "./StdChains.sol";
+import {StdCheats} from "./StdCheats.sol";
+import {StdConstants} from "./StdConstants.sol";
+import {stdError} from "./StdError.sol";
+import {StdInvariant} from "./StdInvariant.sol";
+import {stdJson} from "./StdJson.sol";
+import {stdMath} from "./StdMath.sol";
+import {StdStorage, stdStorage} from "./StdStorage.sol";
+import {StdStyle} from "./StdStyle.sol";
+import {stdToml} from "./StdToml.sol";
+import {StdUtils} from "./StdUtils.sol";
+import {Vm} from "./Vm.sol";
+
+// 📦 BOILERPLATE
+import {TestBase} from "./Base.sol";
+
+// ⭐️ TEST
+abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils {
+ // Note: IS_TEST() must return true.
+ bool public IS_TEST = true;
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/Vm.sol b/lib/signals-implicit-mode/lib/forge-std/src/Vm.sol
new file mode 100644
index 000000000..cd883706a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/Vm.sol
@@ -0,0 +1,2494 @@
+// Automatically @generated by scripts/vm.py. Do not modify manually.
+
+// SPDX-License-Identifier: MIT OR Apache-2.0
+pragma solidity >=0.6.2 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
+/// result in Script simulations differing from on-chain execution. It is recommended to only use
+/// these cheats in scripts.
+interface VmSafe {
+ /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.
+ enum CallerMode {
+ // No caller modification is currently active.
+ None,
+ // A one time broadcast triggered by a `vm.broadcast()` call is currently active.
+ Broadcast,
+ // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
+ RecurrentBroadcast,
+ // A one time prank triggered by a `vm.prank()` call is currently active.
+ Prank,
+ // A recurrent prank triggered by a `vm.startPrank()` call is currently active.
+ RecurrentPrank
+ }
+
+ /// The kind of account access that occurred.
+ enum AccountAccessKind {
+ // The account was called.
+ Call,
+ // The account was called via delegatecall.
+ DelegateCall,
+ // The account was called via callcode.
+ CallCode,
+ // The account was called via staticcall.
+ StaticCall,
+ // The account was created.
+ Create,
+ // The account was selfdestructed.
+ SelfDestruct,
+ // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
+ Resume,
+ // The account's balance was read.
+ Balance,
+ // The account's codesize was read.
+ Extcodesize,
+ // The account's codehash was read.
+ Extcodehash,
+ // The account's code was copied.
+ Extcodecopy
+ }
+
+ /// Forge execution contexts.
+ enum ForgeContext {
+ // Test group execution context (test, coverage or snapshot).
+ TestGroup,
+ // `forge test` execution context.
+ Test,
+ // `forge coverage` execution context.
+ Coverage,
+ // `forge snapshot` execution context.
+ Snapshot,
+ // Script group execution context (dry run, broadcast or resume).
+ ScriptGroup,
+ // `forge script` execution context.
+ ScriptDryRun,
+ // `forge script --broadcast` execution context.
+ ScriptBroadcast,
+ // `forge script --resume` execution context.
+ ScriptResume,
+ // Unknown `forge` execution context.
+ Unknown
+ }
+
+ /// The transaction type (`txType`) of the broadcast.
+ enum BroadcastTxType {
+ // Represents a CALL broadcast tx.
+ Call,
+ // Represents a CREATE broadcast tx.
+ Create,
+ // Represents a CREATE2 broadcast tx.
+ Create2
+ }
+
+ /// An Ethereum log. Returned by `getRecordedLogs`.
+ struct Log {
+ // The topics of the log, including the signature, if any.
+ bytes32[] topics;
+ // The raw data of the log.
+ bytes data;
+ // The address of the log's emitter.
+ address emitter;
+ }
+
+ /// An RPC URL and its alias. Returned by `rpcUrlStructs`.
+ struct Rpc {
+ // The alias of the RPC URL.
+ string key;
+ // The RPC URL.
+ string url;
+ }
+
+ /// An RPC log object. Returned by `eth_getLogs`.
+ struct EthGetLogs {
+ // The address of the log's emitter.
+ address emitter;
+ // The topics of the log, including the signature, if any.
+ bytes32[] topics;
+ // The raw data of the log.
+ bytes data;
+ // The block hash.
+ bytes32 blockHash;
+ // The block number.
+ uint64 blockNumber;
+ // The transaction hash.
+ bytes32 transactionHash;
+ // The transaction index in the block.
+ uint64 transactionIndex;
+ // The log index.
+ uint256 logIndex;
+ // Whether the log was removed.
+ bool removed;
+ }
+
+ /// A single entry in a directory listing. Returned by `readDir`.
+ struct DirEntry {
+ // The error message, if any.
+ string errorMessage;
+ // The path of the entry.
+ string path;
+ // The depth of the entry.
+ uint64 depth;
+ // Whether the entry is a directory.
+ bool isDir;
+ // Whether the entry is a symlink.
+ bool isSymlink;
+ }
+
+ /// Metadata information about a file.
+ /// This structure is returned from the `fsMetadata` function and represents known
+ /// metadata about a file such as its permissions, size, modification
+ /// times, etc.
+ struct FsMetadata {
+ // True if this metadata is for a directory.
+ bool isDir;
+ // True if this metadata is for a symlink.
+ bool isSymlink;
+ // The size of the file, in bytes, this metadata is for.
+ uint256 length;
+ // True if this metadata is for a readonly (unwritable) file.
+ bool readOnly;
+ // The last modification time listed in this metadata.
+ uint256 modified;
+ // The last access time of this metadata.
+ uint256 accessed;
+ // The creation time listed in this metadata.
+ uint256 created;
+ }
+
+ /// A wallet with a public and private key.
+ struct Wallet {
+ // The wallet's address.
+ address addr;
+ // The wallet's public key `X`.
+ uint256 publicKeyX;
+ // The wallet's public key `Y`.
+ uint256 publicKeyY;
+ // The wallet's private key.
+ uint256 privateKey;
+ }
+
+ /// The result of a `tryFfi` call.
+ struct FfiResult {
+ // The exit code of the call.
+ int32 exitCode;
+ // The optionally hex-decoded `stdout` data.
+ bytes stdout;
+ // The `stderr` data.
+ bytes stderr;
+ }
+
+ /// Information on the chain and fork.
+ struct ChainInfo {
+ // The fork identifier. Set to zero if no fork is active.
+ uint256 forkId;
+ // The chain ID of the current fork.
+ uint256 chainId;
+ }
+
+ /// Information about a blockchain.
+ struct Chain {
+ // The chain name.
+ string name;
+ // The chain's Chain ID.
+ uint256 chainId;
+ // The chain's alias. (i.e. what gets specified in `foundry.toml`).
+ string chainAlias;
+ // A default RPC endpoint for this chain.
+ string rpcUrl;
+ }
+
+ /// The result of a `stopAndReturnStateDiff` call.
+ struct AccountAccess {
+ // The chain and fork the access occurred.
+ ChainInfo chainInfo;
+ // The kind of account access that determines what the account is.
+ // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.
+ // If kind is Create, then the account is the newly created account.
+ // If kind is SelfDestruct, then the account is the selfdestruct recipient.
+ // If kind is a Resume, then account represents a account context that has resumed.
+ AccountAccessKind kind;
+ // The account that was accessed.
+ // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
+ address account;
+ // What accessed the account.
+ address accessor;
+ // If the account was initialized or empty prior to the access.
+ // An account is considered initialized if it has code, a
+ // non-zero nonce, or a non-zero balance.
+ bool initialized;
+ // The previous balance of the accessed account.
+ uint256 oldBalance;
+ // The potential new balance of the accessed account.
+ // That is, all balance changes are recorded here, even if reverts occurred.
+ uint256 newBalance;
+ // Code of the account deployed by CREATE.
+ bytes deployedCode;
+ // Value passed along with the account access
+ uint256 value;
+ // Input data provided to the CREATE or CALL
+ bytes data;
+ // If this access reverted in either the current or parent context.
+ bool reverted;
+ // An ordered list of storage accesses made during an account access operation.
+ StorageAccess[] storageAccesses;
+ // Call depth traversed during the recording of state differences
+ uint64 depth;
+ // The previous nonce of the accessed account.
+ uint64 oldNonce;
+ // The new nonce of the accessed account.
+ uint64 newNonce;
+ }
+
+ /// The storage accessed during an `AccountAccess`.
+ struct StorageAccess {
+ // The account whose storage was accessed.
+ address account;
+ // The slot that was accessed.
+ bytes32 slot;
+ // If the access was a write.
+ bool isWrite;
+ // The previous value of the slot.
+ bytes32 previousValue;
+ // The new value of the slot.
+ bytes32 newValue;
+ // If the access was reverted.
+ bool reverted;
+ }
+
+ /// Gas used. Returned by `lastCallGas`.
+ struct Gas {
+ // The gas limit of the call.
+ uint64 gasLimit;
+ // The total gas used.
+ uint64 gasTotalUsed;
+ // DEPRECATED: The amount of gas used for memory expansion. Ref:
+ uint64 gasMemoryUsed;
+ // The amount of gas refunded.
+ int64 gasRefunded;
+ // The amount of gas remaining.
+ uint64 gasRemaining;
+ }
+
+ /// The result of the `stopDebugTraceRecording` call
+ struct DebugStep {
+ // The stack before executing the step of the run.
+ // stack\[0\] represents the top of the stack.
+ // and only stack data relevant to the opcode execution is contained.
+ uint256[] stack;
+ // The memory input data before executing the step of the run.
+ // only input data relevant to the opcode execution is contained.
+ // e.g. for MLOAD, it will have memory\[offset:offset+32\] copied here.
+ // the offset value can be get by the stack data.
+ bytes memoryInput;
+ // The opcode that was accessed.
+ uint8 opcode;
+ // The call depth of the step.
+ uint64 depth;
+ // Whether the call end up with out of gas error.
+ bool isOutOfGas;
+ // The contract address where the opcode is running
+ address contractAddr;
+ }
+
+ /// Represents a transaction's broadcast details.
+ struct BroadcastTxSummary {
+ // The hash of the transaction that was broadcasted
+ bytes32 txHash;
+ // Represent the type of transaction among CALL, CREATE, CREATE2
+ BroadcastTxType txType;
+ // The address of the contract that was called or created.
+ // This is address of the contract that is created if the txType is CREATE or CREATE2.
+ address contractAddress;
+ // The block number the transaction landed in.
+ uint64 blockNumber;
+ // Status of the transaction, retrieved from the transaction receipt.
+ bool success;
+ }
+
+ /// Holds a signed EIP-7702 authorization for an authority account to delegate to an implementation.
+ struct SignedDelegation {
+ // The y-parity of the recovered secp256k1 signature (0 or 1).
+ uint8 v;
+ // First 32 bytes of the signature.
+ bytes32 r;
+ // Second 32 bytes of the signature.
+ bytes32 s;
+ // The current nonce of the authority account at signing time.
+ // Used to ensure signature can't be replayed after account nonce changes.
+ uint64 nonce;
+ // Address of the contract implementation that will be delegated to.
+ // Gets encoded into delegation code: 0xef0100 || implementation.
+ address implementation;
+ }
+
+ /// Represents a "potential" revert reason from a single subsequent call when using `vm.assumeNoReverts`.
+ /// Reverts that match will result in a FOUNDRY::ASSUME rejection, whereas unmatched reverts will be surfaced
+ /// as normal.
+ struct PotentialRevert {
+ // The allowed origin of the revert opcode; address(0) allows reverts from any address
+ address reverter;
+ // When true, only matches on the beginning of the revert data, otherwise, matches on entire revert data
+ bool partialMatch;
+ // The data to use to match encountered reverts
+ bytes revertData;
+ }
+
+ /// An EIP-2930 access list item.
+ struct AccessListItem {
+ // The address to be added in access list.
+ address target;
+ // The storage keys to be added in access list.
+ bytes32[] storageKeys;
+ }
+
+ // ======== Crypto ========
+
+ /// Derives a private key from the name, labels the account with that name, and returns the wallet.
+ function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);
+
+ /// Generates a wallet from the private key and returns the wallet.
+ function createWallet(uint256 privateKey) external returns (Wallet memory wallet);
+
+ /// Generates a wallet from the private key, labels the account with that name, and returns the wallet.
+ function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);
+
+ /// Derive a private key from a provided mnemonic string (or mnemonic file path)
+ /// at the derivation path `m/44'/60'/0'/0/{index}`.
+ function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
+
+ /// Derive a private key from a provided mnemonic string (or mnemonic file path)
+ /// at `{derivationPath}{index}`.
+ function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
+ external
+ pure
+ returns (uint256 privateKey);
+
+ /// Derive a private key from a provided mnemonic string (or mnemonic file path) in the specified language
+ /// at the derivation path `m/44'/60'/0'/0/{index}`.
+ function deriveKey(string calldata mnemonic, uint32 index, string calldata language)
+ external
+ pure
+ returns (uint256 privateKey);
+
+ /// Derive a private key from a provided mnemonic string (or mnemonic file path) in the specified language
+ /// at `{derivationPath}{index}`.
+ function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language)
+ external
+ pure
+ returns (uint256 privateKey);
+
+ /// Derives secp256r1 public key from the provided `privateKey`.
+ function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY);
+
+ /// Adds a private key to the local forge wallet and returns the address.
+ function rememberKey(uint256 privateKey) external returns (address keyAddr);
+
+ /// Derive a set number of wallets from a mnemonic at the derivation path `m/44'/60'/0'/0/{0..count}`.
+ /// The respective private keys are saved to the local forge wallet for later use and their addresses are returned.
+ function rememberKeys(string calldata mnemonic, string calldata derivationPath, uint32 count)
+ external
+ returns (address[] memory keyAddrs);
+
+ /// Derive a set number of wallets from a mnemonic in the specified language at the derivation path `m/44'/60'/0'/0/{0..count}`.
+ /// The respective private keys are saved to the local forge wallet for later use and their addresses are returned.
+ function rememberKeys(
+ string calldata mnemonic,
+ string calldata derivationPath,
+ string calldata language,
+ uint32 count
+ ) external returns (address[] memory keyAddrs);
+
+ /// Signs data with a `Wallet`.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with `privateKey` using the secp256k1 curve.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ /// If `--sender` is provided, the signer with provided address is used, otherwise,
+ /// if exactly one signer is provided to the script, that signer is used.
+ /// Raises error if signer passed through `--sender` does not match any unlocked signers or
+ /// if `--sender` is not provided and not exactly one signer is passed to the script.
+ function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ /// Raises error if none of the signers passed into the script have provided address.
+ function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with `privateKey` using the secp256r1 curve.
+ function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s);
+
+ /// Signs data with a `Wallet`.
+ function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
+
+ /// Signs `digest` with `privateKey` using the secp256k1 curve.
+ function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// If `--sender` is provided, the signer with provided address is used, otherwise,
+ /// if exactly one signer is provided to the script, that signer is used.
+ /// Raises error if signer passed through `--sender` does not match any unlocked signers or
+ /// if `--sender` is not provided and not exactly one signer is passed to the script.
+ function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// Raises error if none of the signers passed into the script have provided address.
+ function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
+
+ // ======== Environment ========
+
+ /// Gets the environment variable `name` and parses it as `address`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envAddress(string calldata name) external view returns (address value);
+
+ /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bool`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBool(string calldata name) external view returns (bool value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bytes32`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes32(string calldata name) external view returns (bytes32 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bytes`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes(string calldata name) external view returns (bytes memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
+
+ /// Gets the environment variable `name` and returns true if it exists, else returns false.
+ function envExists(string calldata name) external view returns (bool result);
+
+ /// Gets the environment variable `name` and parses it as `int256`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envInt(string calldata name) external view returns (int256 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bool`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, bool defaultValue) external view returns (bool value);
+
+ /// Gets the environment variable `name` and parses it as `uint256`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
+ external
+ view
+ returns (address[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
+ external
+ view
+ returns (bytes32[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
+ external
+ view
+ returns (string[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
+ external
+ view
+ returns (bytes[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `int256`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, int256 defaultValue) external view returns (int256 value);
+
+ /// Gets the environment variable `name` and parses it as `address`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, address defaultValue) external view returns (address value);
+
+ /// Gets the environment variable `name` and parses it as `bytes32`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value);
+
+ /// Gets the environment variable `name` and parses it as `string`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value);
+
+ /// Gets the environment variable `name` and parses it as `bytes`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
+ external
+ view
+ returns (bool[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
+ external
+ view
+ returns (uint256[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
+ external
+ view
+ returns (int256[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `string`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envString(string calldata name) external view returns (string memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `uint256`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envUint(string calldata name) external view returns (uint256 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
+
+ /// Returns true if `forge` command was executed in given context.
+ function isContext(ForgeContext context) external view returns (bool result);
+
+ /// Resolves the env variable placeholders of a given input string.
+ function resolveEnv(string calldata input) external returns (string memory);
+
+ /// Sets environment variables.
+ function setEnv(string calldata name, string calldata value) external;
+
+ // ======== EVM ========
+
+ /// Gets all accessed reads and write slot from a `vm.record` session, for a given address.
+ function accesses(address target) external view returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
+
+ /// Gets the address for a given private key.
+ function addr(uint256 privateKey) external pure returns (address keyAddr);
+
+ /// Gets all the logs according to specified filter.
+ function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
+ external
+ view
+ returns (EthGetLogs[] memory logs);
+
+ /// Gets the current `block.blobbasefee`.
+ /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,
+ /// and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getBlobBaseFee() external view returns (uint256 blobBaseFee);
+
+ /// Gets the current `block.number`.
+ /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,
+ /// and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getBlockNumber() external view returns (uint256 height);
+
+ /// Gets the current `block.timestamp`.
+ /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,
+ /// and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getBlockTimestamp() external view returns (uint256 timestamp);
+
+ /// Gets the current `block.chainid` of the currently selected environment.
+ /// You should use this instead of `block.chainid` if you use `vm.selectFork` or `vm.createSelectFork`, as `block.chainid` could be assumed
+ /// to be constant across a transaction, and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getChainId() external view returns (uint256 blockChainId);
+
+ /// Gets the map key and parent of a mapping at a given slot, for a given address.
+ function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
+ external
+ view
+ returns (bool found, bytes32 key, bytes32 parent);
+
+ /// Gets the number of elements in the mapping at the given slot, for a given address.
+ function getMappingLength(address target, bytes32 mappingSlot) external view returns (uint256 length);
+
+ /// Gets the elements at index idx of the mapping at the given slot, for a given address. The
+ /// index must be less than the length of the mapping (i.e. the number of keys in the mapping).
+ function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external view returns (bytes32 value);
+
+ /// Gets the nonce of an account.
+ function getNonce(address account) external view returns (uint64 nonce);
+
+ /// Get the nonce of a `Wallet`.
+ function getNonce(Wallet calldata wallet) external view returns (uint64 nonce);
+
+ /// Gets the RLP encoded block header for a given block number.
+ /// Returns the block header in the same format as `cast block --raw`.
+ function getRawBlockHeader(uint256 blockNumber) external view returns (bytes memory rlpHeader);
+
+ /// Gets all the recorded logs.
+ function getRecordedLogs() external view returns (Log[] memory logs);
+
+ /// Returns state diffs from current `vm.startStateDiffRecording` session.
+ function getStateDiff() external view returns (string memory diff);
+
+ /// Returns state diffs from current `vm.startStateDiffRecording` session, in json format.
+ function getStateDiffJson() external view returns (string memory diff);
+
+ /// Returns an array of `StorageAccess` from current `vm.stateStateDiffRecording` session
+ function getStorageAccesses() external view returns (StorageAccess[] memory storageAccesses);
+
+ /// Gets the gas used in the last call from the callee perspective.
+ function lastCallGas() external view returns (Gas memory gas);
+
+ /// Loads a storage slot from an address.
+ function load(address target, bytes32 slot) external view returns (bytes32 data);
+
+ /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
+ function pauseGasMetering() external;
+
+ /// Records all storage reads and writes. Use `accesses` to get the recorded data.
+ /// Subsequent calls to `record` will clear the previous data.
+ function record() external;
+
+ /// Record all the transaction logs.
+ function recordLogs() external;
+
+ /// Reset gas metering (i.e. gas usage is set to gas limit).
+ function resetGasMetering() external;
+
+ /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
+ function resumeGasMetering() external;
+
+ /// Performs an Ethereum JSON-RPC request to the current fork URL.
+ function rpc(string calldata method, string calldata params) external returns (bytes memory data);
+
+ /// Performs an Ethereum JSON-RPC request to the given endpoint.
+ function rpc(string calldata urlOrAlias, string calldata method, string calldata params)
+ external
+ returns (bytes memory data);
+
+ /// Records the debug trace during the run.
+ function startDebugTraceRecording() external;
+
+ /// Starts recording all map SSTOREs for later retrieval.
+ function startMappingRecording() external;
+
+ /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
+ /// along with the context of the calls
+ function startStateDiffRecording() external;
+
+ /// Stop debug trace recording and returns the recorded debug trace.
+ function stopAndReturnDebugTraceRecording() external returns (DebugStep[] memory step);
+
+ /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
+ function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);
+
+ /// Stops recording all map SSTOREs for later retrieval and clears the recorded data.
+ function stopMappingRecording() external;
+
+ /// Stops recording storage reads and writes.
+ function stopRecord() external;
+
+ // ======== Filesystem ========
+
+ /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
+ /// `path` is relative to the project root.
+ function closeFile(string calldata path) external;
+
+ /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
+ /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
+ /// Both `from` and `to` are relative to the project root.
+ function copyFile(string calldata from, string calldata to) external returns (uint64 copied);
+
+ /// Creates a new, empty directory at the provided path.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - User lacks permissions to modify `path`.
+ /// - A parent of the given path doesn't exist and `recursive` is false.
+ /// - `path` already exists and `recursive` is false.
+ /// `path` is relative to the project root.
+ function createDir(string calldata path, bool recursive) external;
+
+ /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function deployCode(string calldata artifactPath) external returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts abi-encoded constructor arguments.
+ function deployCode(string calldata artifactPath, bytes calldata constructorArgs)
+ external
+ returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts `msg.value`.
+ function deployCode(string calldata artifactPath, uint256 value) external returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts abi-encoded constructor arguments and `msg.value`.
+ function deployCode(string calldata artifactPath, bytes calldata constructorArgs, uint256 value)
+ external
+ returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function deployCode(string calldata artifactPath, bytes32 salt) external returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts abi-encoded constructor arguments.
+ function deployCode(string calldata artifactPath, bytes calldata constructorArgs, bytes32 salt)
+ external
+ returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts `msg.value`.
+ function deployCode(string calldata artifactPath, uint256 value, bytes32 salt)
+ external
+ returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file, using the CREATE2 salt. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts abi-encoded constructor arguments and `msg.value`.
+ function deployCode(string calldata artifactPath, bytes calldata constructorArgs, uint256 value, bytes32 salt)
+ external
+ returns (address deployedAddress);
+
+ /// Returns true if the given path points to an existing entity, else returns false.
+ function exists(string calldata path) external view returns (bool result);
+
+ /// Performs a foreign function call via the terminal.
+ function ffi(string[] calldata commandInput) external returns (bytes memory result);
+
+ /// Given a path, query the file system to get information about a file, directory, etc.
+ function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);
+
+ /// Gets the artifact path from code (aka. creation code).
+ function getArtifactPathByCode(bytes calldata code) external view returns (string memory path);
+
+ /// Gets the artifact path from deployed code (aka. runtime code).
+ function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path);
+
+ /// Returns the most recent broadcast for the given contract on `chainId` matching `txType`.
+ /// For example:
+ /// The most recent deployment can be fetched by passing `txType` as `CREATE` or `CREATE2`.
+ /// The most recent call can be fetched by passing `txType` as `CALL`.
+ function getBroadcast(string calldata contractName, uint64 chainId, BroadcastTxType txType)
+ external
+ view
+ returns (BroadcastTxSummary memory);
+
+ /// Returns all broadcasts for the given contract on `chainId` with the specified `txType`.
+ /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.
+ function getBroadcasts(string calldata contractName, uint64 chainId, BroadcastTxType txType)
+ external
+ view
+ returns (BroadcastTxSummary[] memory);
+
+ /// Returns all broadcasts for the given contract on `chainId`.
+ /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.
+ function getBroadcasts(string calldata contractName, uint64 chainId)
+ external
+ view
+ returns (BroadcastTxSummary[] memory);
+
+ /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
+
+ /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
+
+ /// Returns the most recent deployment for the current `chainId`.
+ function getDeployment(string calldata contractName) external view returns (address deployedAddress);
+
+ /// Returns the most recent deployment for the given contract on `chainId`
+ function getDeployment(string calldata contractName, uint64 chainId)
+ external
+ view
+ returns (address deployedAddress);
+
+ /// Returns all deployments for the given contract on `chainId`
+ /// Sorted in descending order of deployment time i.e descending order of BroadcastTxSummary.blockNumber.
+ /// The most recent deployment is the first element, and the oldest is the last.
+ function getDeployments(string calldata contractName, uint64 chainId)
+ external
+ view
+ returns (address[] memory deployedAddresses);
+
+ /// Returns true if the path exists on disk and is pointing at a directory, else returns false.
+ function isDir(string calldata path) external view returns (bool result);
+
+ /// Returns true if the path exists on disk and is pointing at a regular file, else returns false.
+ function isFile(string calldata path) external view returns (bool result);
+
+ /// Get the path of the current project root.
+ function projectRoot() external view returns (string memory path);
+
+ /// Prompts the user for a string value in the terminal.
+ function prompt(string calldata promptText) external returns (string memory input);
+
+ /// Prompts the user for an address in the terminal.
+ function promptAddress(string calldata promptText) external returns (address);
+
+ /// Prompts the user for a hidden string value in the terminal.
+ function promptSecret(string calldata promptText) external returns (string memory input);
+
+ /// Prompts the user for hidden uint256 in the terminal (usually pk).
+ function promptSecretUint(string calldata promptText) external returns (uint256);
+
+ /// Prompts the user for uint256 in the terminal.
+ function promptUint(string calldata promptText) external returns (uint256);
+
+ /// Reads the directory at the given path recursively, up to `maxDepth`.
+ /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned.
+ /// Follows symbolic links if `followLinks` is true.
+ function readDir(string calldata path) external view returns (DirEntry[] memory entries);
+
+ /// See `readDir(string)`.
+ function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
+
+ /// See `readDir(string)`.
+ function readDir(string calldata path, uint64 maxDepth, bool followLinks)
+ external
+ view
+ returns (DirEntry[] memory entries);
+
+ /// Reads the entire content of file to string. `path` is relative to the project root.
+ function readFile(string calldata path) external view returns (string memory data);
+
+ /// Reads the entire content of file as binary. `path` is relative to the project root.
+ function readFileBinary(string calldata path) external view returns (bytes memory data);
+
+ /// Reads next line of file to string.
+ function readLine(string calldata path) external view returns (string memory line);
+
+ /// Reads a symbolic link, returning the path that the link points to.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - `path` is not a symbolic link.
+ /// - `path` does not exist.
+ function readLink(string calldata linkPath) external view returns (string memory targetPath);
+
+ /// Removes a directory at the provided path.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - `path` doesn't exist.
+ /// - `path` isn't a directory.
+ /// - User lacks permissions to modify `path`.
+ /// - The directory is not empty and `recursive` is false.
+ /// `path` is relative to the project root.
+ function removeDir(string calldata path, bool recursive) external;
+
+ /// Removes a file from the filesystem.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - `path` points to a directory.
+ /// - The file doesn't exist.
+ /// - The user lacks permissions to remove the file.
+ /// `path` is relative to the project root.
+ function removeFile(string calldata path) external;
+
+ /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr.
+ function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);
+
+ /// Returns the time since unix epoch in milliseconds.
+ function unixTime() external view returns (uint256 milliseconds);
+
+ /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
+ /// `path` is relative to the project root.
+ function writeFile(string calldata path, string calldata data) external;
+
+ /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
+ /// `path` is relative to the project root.
+ function writeFileBinary(string calldata path, bytes calldata data) external;
+
+ /// Writes line to file, creating a file if it does not exist.
+ /// `path` is relative to the project root.
+ function writeLine(string calldata path, string calldata data) external;
+
+ // ======== JSON ========
+
+ /// Checks if `key` exists in a JSON object.
+ function keyExistsJson(string calldata json, string calldata key) external view returns (bool);
+
+ /// Parses a string of JSON data at `key` and coerces it to `address`.
+ function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
+
+ /// Parses a string of JSON data at `key` and coerces it to `address[]`.
+ function parseJsonAddressArray(string calldata json, string calldata key)
+ external
+ pure
+ returns (address[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bool`.
+ function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bool[]`.
+ function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes`.
+ function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes32`.
+ function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.
+ function parseJsonBytes32Array(string calldata json, string calldata key)
+ external
+ pure
+ returns (bytes32[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes[]`.
+ function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `int256`.
+ function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
+
+ /// Parses a string of JSON data at `key` and coerces it to `int256[]`.
+ function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
+
+ /// Returns an array of all the keys in a JSON object.
+ function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);
+
+ /// Parses a string of JSON data at `key` and coerces it to `string`.
+ function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `string[]`.
+ function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`.
+ function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`.
+ function parseJsonType(string calldata json, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`.
+ function parseJsonType(string calldata json, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `uint256`.
+ function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);
+
+ /// Parses a string of JSON data at `key` and coerces it to `uint256[]`.
+ function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);
+
+ /// ABI-encodes a JSON object.
+ function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);
+
+ /// ABI-encodes a JSON object at `key`.
+ function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
+
+ /// See `serializeJson`.
+ function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
+ external
+ returns (string memory json);
+
+ /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file.
+ /// Returns the stringified version of the specific JSON file up to that moment.
+ function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeJsonType(string calldata typeDescription, bytes calldata value)
+ external
+ pure
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeJsonType(
+ string calldata objectKey,
+ string calldata valueKey,
+ string calldata typeDescription,
+ bytes calldata value
+ ) external returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
+ external
+ returns (string memory json);
+
+ /// Write a serialized JSON object to a file. If the file exists, it will be overwritten.
+ function writeJson(string calldata json, string calldata path) external;
+
+ /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key =
+ /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing.
+ /// This cheatcode will create new keys if they didn't previously exist.
+ function writeJson(string calldata json, string calldata path, string calldata valueKey) external;
+
+ /// Checks if `key` exists in a JSON object
+ /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions.
+ function keyExists(string calldata json, string calldata key) external view returns (bool);
+
+ // ======== Scripting ========
+
+ /// Attach an EIP-4844 blob to the next call
+ function attachBlob(bytes calldata blob) external;
+
+ /// Designate the next call as an EIP-7702 transaction
+ function attachDelegation(SignedDelegation calldata signedDelegation) external;
+
+ /// Designate the next call as an EIP-7702 transaction, with optional cross-chain validity.
+ function attachDelegation(SignedDelegation calldata signedDelegation, bool crossChain) external;
+
+ /// Takes a signed transaction and broadcasts it to the network.
+ function broadcastRawTransaction(bytes calldata data) external;
+
+ /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain.
+ /// Broadcasting address is determined by checking the following in order:
+ /// 1. If `--sender` argument was provided, that address is used.
+ /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
+ /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
+ function broadcast() external;
+
+ /// Has the next call (at this call depth only) create a transaction with the address provided
+ /// as the sender that can later be signed and sent onchain.
+ function broadcast(address signer) external;
+
+ /// Has the next call (at this call depth only) create a transaction with the private key
+ /// provided as the sender that can later be signed and sent onchain.
+ function broadcast(uint256 privateKey) external;
+
+ /// Returns addresses of available unlocked wallets in the script environment.
+ function getWallets() external view returns (address[] memory wallets);
+
+ /// Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction
+ function signAndAttachDelegation(address implementation, uint256 privateKey)
+ external
+ returns (SignedDelegation memory signedDelegation);
+
+ /// Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction for specific nonce
+ function signAndAttachDelegation(address implementation, uint256 privateKey, uint64 nonce)
+ external
+ returns (SignedDelegation memory signedDelegation);
+
+ /// Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction, with optional cross-chain validity.
+ function signAndAttachDelegation(address implementation, uint256 privateKey, bool crossChain)
+ external
+ returns (SignedDelegation memory signedDelegation);
+
+ /// Sign an EIP-7702 authorization for delegation
+ function signDelegation(address implementation, uint256 privateKey)
+ external
+ returns (SignedDelegation memory signedDelegation);
+
+ /// Sign an EIP-7702 authorization for delegation for specific nonce
+ function signDelegation(address implementation, uint256 privateKey, uint64 nonce)
+ external
+ returns (SignedDelegation memory signedDelegation);
+
+ /// Sign an EIP-7702 authorization for delegation, with optional cross-chain validity.
+ function signDelegation(address implementation, uint256 privateKey, bool crossChain)
+ external
+ returns (SignedDelegation memory signedDelegation);
+
+ /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain.
+ /// Broadcasting address is determined by checking the following in order:
+ /// 1. If `--sender` argument was provided, that address is used.
+ /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
+ /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
+ function startBroadcast() external;
+
+ /// Has all subsequent calls (at this call depth only) create transactions with the address
+ /// provided that can later be signed and sent onchain.
+ function startBroadcast(address signer) external;
+
+ /// Has all subsequent calls (at this call depth only) create transactions with the private key
+ /// provided that can later be signed and sent onchain.
+ function startBroadcast(uint256 privateKey) external;
+
+ /// Stops collecting onchain transactions.
+ function stopBroadcast() external;
+
+ // ======== String ========
+
+ /// Returns true if `search` is found in `subject`, false otherwise.
+ function contains(string calldata subject, string calldata search) external pure returns (bool result);
+
+ /// Returns the index of the first occurrence of a `key` in an `input` string.
+ /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found.
+ /// Returns 0 in case of an empty `key`.
+ function indexOf(string calldata input, string calldata key) external pure returns (uint256);
+
+ /// Parses the given `string` into an `address`.
+ function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
+
+ /// Parses the given `string` into a `bool`.
+ function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);
+
+ /// Parses the given `string` into `bytes`.
+ function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
+
+ /// Parses the given `string` into a `bytes32`.
+ function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
+
+ /// Parses the given `string` into a `int256`.
+ function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
+
+ /// Parses the given `string` into a `uint256`.
+ function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
+
+ /// Replaces occurrences of `from` in the given `string` with `to`.
+ function replace(string calldata input, string calldata from, string calldata to)
+ external
+ pure
+ returns (string memory output);
+
+ /// Splits the given `string` into an array of strings divided by the `delimiter`.
+ function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs);
+
+ /// Converts the given `string` value to Lowercase.
+ function toLowercase(string calldata input) external pure returns (string memory output);
+
+ /// Converts the given value to a `string`.
+ function toString(address value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(bytes32 value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(bool value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(uint256 value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(int256 value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given `string` value to Uppercase.
+ function toUppercase(string calldata input) external pure returns (string memory output);
+
+ /// Trims leading and trailing whitespace from the given `string` value.
+ function trim(string calldata input) external pure returns (string memory output);
+
+ // ======== Testing ========
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message.
+ function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqAbsDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message.
+ function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqAbsDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure;
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Includes error message into revert string on failure.
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Includes error message into revert string on failure.
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message.
+ function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals)
+ external
+ pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqRelDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message.
+ function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals)
+ external
+ pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqRelDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Includes error message into revert string on failure.
+ function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error)
+ external
+ pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Includes error message into revert string on failure.
+ function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error)
+ external
+ pure;
+
+ /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `bool` values are equal.
+ function assertEq(bool left, bool right) external pure;
+
+ /// Asserts that two `bool` values are equal and includes error message into revert string on failure.
+ function assertEq(bool left, bool right, string calldata error) external pure;
+
+ /// Asserts that two `string` values are equal.
+ function assertEq(string calldata left, string calldata right) external pure;
+
+ /// Asserts that two `string` values are equal and includes error message into revert string on failure.
+ function assertEq(string calldata left, string calldata right, string calldata error) external pure;
+
+ /// Asserts that two `bytes` values are equal.
+ function assertEq(bytes calldata left, bytes calldata right) external pure;
+
+ /// Asserts that two `bytes` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bool` values are equal.
+ function assertEq(bool[] calldata left, bool[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.
+ function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `uint256 values are equal.
+ function assertEq(uint256[] calldata left, uint256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.
+ function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `int256` values are equal.
+ function assertEq(int256[] calldata left, int256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.
+ function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are equal.
+ function assertEq(uint256 left, uint256 right) external pure;
+
+ /// Asserts that two arrays of `address` values are equal.
+ function assertEq(address[] calldata left, address[] calldata right) external pure;
+
+ /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.
+ function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are equal.
+ function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `string` values are equal.
+ function assertEq(string[] calldata left, string[] calldata right) external pure;
+
+ /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.
+ function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes` values are equal.
+ function assertEq(bytes[] calldata left, bytes[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are equal and includes error message into revert string on failure.
+ function assertEq(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are equal.
+ function assertEq(int256 left, int256 right) external pure;
+
+ /// Asserts that two `int256` values are equal and includes error message into revert string on failure.
+ function assertEq(int256 left, int256 right, string calldata error) external pure;
+
+ /// Asserts that two `address` values are equal.
+ function assertEq(address left, address right) external pure;
+
+ /// Asserts that two `address` values are equal and includes error message into revert string on failure.
+ function assertEq(address left, address right, string calldata error) external pure;
+
+ /// Asserts that two `bytes32` values are equal.
+ function assertEq(bytes32 left, bytes32 right) external pure;
+
+ /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes32 left, bytes32 right, string calldata error) external pure;
+
+ /// Asserts that the given condition is false.
+ function assertFalse(bool condition) external pure;
+
+ /// Asserts that the given condition is false and includes error message into revert string on failure.
+ function assertFalse(bool condition, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ function assertGe(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertGe(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ function assertGe(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertGe(int256 left, int256 right, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message.
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message.
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ function assertGt(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ /// Includes error message into revert string on failure.
+ function assertGt(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ function assertGt(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ /// Includes error message into revert string on failure.
+ function assertGt(int256 left, int256 right, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ function assertLe(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertLe(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ function assertLe(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertLe(int256 left, int256 right, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message.
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message.
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ function assertLt(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ /// Includes error message into revert string on failure.
+ function assertLt(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ function assertLt(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ /// Includes error message into revert string on failure.
+ function assertLt(int256 left, int256 right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `bool` values are not equal.
+ function assertNotEq(bool left, bool right) external pure;
+
+ /// Asserts that two `bool` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bool left, bool right, string calldata error) external pure;
+
+ /// Asserts that two `string` values are not equal.
+ function assertNotEq(string calldata left, string calldata right) external pure;
+
+ /// Asserts that two `string` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(string calldata left, string calldata right, string calldata error) external pure;
+
+ /// Asserts that two `bytes` values are not equal.
+ function assertNotEq(bytes calldata left, bytes calldata right) external pure;
+
+ /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bool` values are not equal.
+ function assertNotEq(bool[] calldata left, bool[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `uint256` values are not equal.
+ function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `int256` values are not equal.
+ function assertNotEq(int256[] calldata left, int256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are not equal.
+ function assertNotEq(uint256 left, uint256 right) external pure;
+
+ /// Asserts that two arrays of `address` values are not equal.
+ function assertNotEq(address[] calldata left, address[] calldata right) external pure;
+
+ /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are not equal.
+ function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `string` values are not equal.
+ function assertNotEq(string[] calldata left, string[] calldata right) external pure;
+
+ /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes` values are not equal.
+ function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are not equal.
+ function assertNotEq(int256 left, int256 right) external pure;
+
+ /// Asserts that two `int256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(int256 left, int256 right, string calldata error) external pure;
+
+ /// Asserts that two `address` values are not equal.
+ function assertNotEq(address left, address right) external pure;
+
+ /// Asserts that two `address` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(address left, address right, string calldata error) external pure;
+
+ /// Asserts that two `bytes32` values are not equal.
+ function assertNotEq(bytes32 left, bytes32 right) external pure;
+
+ /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure;
+
+ /// Asserts that the given condition is true.
+ function assertTrue(bool condition) external pure;
+
+ /// Asserts that the given condition is true and includes error message into revert string on failure.
+ function assertTrue(bool condition, string calldata error) external pure;
+
+ /// If the condition is false, discard this run's fuzz inputs and generate new ones.
+ function assume(bool condition) external pure;
+
+ /// Discard this run's fuzz inputs and generate new ones if next call reverted.
+ function assumeNoRevert() external pure;
+
+ /// Discard this run's fuzz inputs and generate new ones if next call reverts with the potential revert parameters.
+ function assumeNoRevert(PotentialRevert calldata potentialRevert) external pure;
+
+ /// Discard this run's fuzz inputs and generate new ones if next call reverts with the any of the potential revert parameters.
+ function assumeNoRevert(PotentialRevert[] calldata potentialReverts) external pure;
+
+ /// Writes a breakpoint to jump to in the debugger.
+ function breakpoint(string calldata char) external pure;
+
+ /// Writes a conditional breakpoint to jump to in the debugger.
+ function breakpoint(string calldata char, bool value) external pure;
+
+ /// Returns true if the current Foundry version is greater than or equal to the given version.
+ /// The given version string must be in the format `major.minor.patch`.
+ /// This is equivalent to `foundryVersionCmp(version) >= 0`.
+ function foundryVersionAtLeast(string calldata version) external view returns (bool);
+
+ /// Compares the current Foundry version with the given version string.
+ /// The given version string must be in the format `major.minor.patch`.
+ /// Returns:
+ /// -1 if current Foundry version is less than the given version
+ /// 0 if current Foundry version equals the given version
+ /// 1 if current Foundry version is greater than the given version
+ /// This result can then be used with a comparison operator against `0`.
+ /// For example, to check if the current Foundry version is greater than or equal to `1.0.0`:
+ /// `if (foundryVersionCmp("1.0.0") >= 0) { ... }`
+ function foundryVersionCmp(string calldata version) external view returns (int256);
+
+ /// Returns a Chain struct for specific alias
+ function getChain(string calldata chainAlias) external view returns (Chain memory chain);
+
+ /// Returns a Chain struct for specific chainId
+ function getChain(uint256 chainId) external view returns (Chain memory chain);
+
+ /// Returns the Foundry version.
+ /// Format: -+..
+ /// Sample output: 0.3.0-nightly+3cb96bde9b.1737036656.debug
+ /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs.
+ /// For reliable version comparisons, use UNIX format (e.g., >= 1700000000)
+ /// to compare timestamps while ignoring minor time differences.
+ function getFoundryVersion() external view returns (string memory version);
+
+ /// Returns the RPC url for the given alias.
+ function rpcUrl(string calldata rpcAlias) external view returns (string memory json);
+
+ /// Returns all rpc urls and their aliases as structs.
+ function rpcUrlStructs() external view returns (Rpc[] memory urls);
+
+ /// Returns all rpc urls and their aliases `[alias, url][]`.
+ function rpcUrls() external view returns (string[2][] memory urls);
+
+ /// Suspends execution of the main thread for `duration` milliseconds.
+ function sleep(uint256 duration) external;
+
+ // ======== Toml ========
+
+ /// Checks if `key` exists in a TOML table.
+ function keyExistsToml(string calldata toml, string calldata key) external view returns (bool);
+
+ /// Parses a string of TOML data at `key` and coerces it to `address`.
+ function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address);
+
+ /// Parses a string of TOML data at `key` and coerces it to `address[]`.
+ function parseTomlAddressArray(string calldata toml, string calldata key)
+ external
+ pure
+ returns (address[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bool`.
+ function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bool[]`.
+ function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes`.
+ function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes32`.
+ function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`.
+ function parseTomlBytes32Array(string calldata toml, string calldata key)
+ external
+ pure
+ returns (bytes32[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes[]`.
+ function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `int256`.
+ function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256);
+
+ /// Parses a string of TOML data at `key` and coerces it to `int256[]`.
+ function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory);
+
+ /// Returns an array of all the keys in a TOML table.
+ function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys);
+
+ /// Parses a string of TOML data at `key` and coerces it to `string`.
+ function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `string[]`.
+ function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`.
+ function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`.
+ function parseTomlType(string calldata toml, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`.
+ function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `uint256`.
+ function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256);
+
+ /// Parses a string of TOML data at `key` and coerces it to `uint256[]`.
+ function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory);
+
+ /// ABI-encodes a TOML table.
+ function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData);
+
+ /// ABI-encodes a TOML table at `key`.
+ function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData);
+
+ /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file.
+ function writeToml(string calldata json, string calldata path) external;
+
+ /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key =
+ /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing.
+ /// This cheatcode will create new keys if they didn't previously exist.
+ function writeToml(string calldata json, string calldata path, string calldata valueKey) external;
+
+ // ======== Utilities ========
+
+ /// Returns an uint256 value bounded in given range and different from the current one.
+ function bound(uint256 current, uint256 min, uint256 max) external view returns (uint256);
+
+ /// Returns an int256 value bounded in given range and different from the current one.
+ function bound(int256 current, int256 min, int256 max) external view returns (int256);
+
+ /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.
+ function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
+ external
+ pure
+ returns (address);
+
+ /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer.
+ function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);
+
+ /// Compute the address a contract will be deployed at for a given deployer address and nonce.
+ function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address);
+
+ /// Utility cheatcode to copy storage of `from` contract to another `to` contract.
+ function copyStorage(address from, address to) external;
+
+ /// Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data.
+ /// Supports 2 different inputs:
+ /// 1. Name of the type (i.e. "PermitSingle"):
+ /// * requires previous binding generation with `forge bind-json`.
+ /// * bindings will be retrieved from the path configured in `foundry.toml`.
+ /// 2. String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)").
+ /// * Note: the cheatcode will use the canonical type even if the input is malformated
+ /// with the wrong order of elements or with extra whitespaces.
+ function eip712HashStruct(string calldata typeNameOrDefinition, bytes calldata abiEncodedData)
+ external
+ pure
+ returns (bytes32 typeHash);
+
+ /// Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data.
+ /// Requires previous binding generation with `forge bind-json`.
+ /// Params:
+ /// * `bindingsPath`: path where the output of `forge bind-json` is stored.
+ /// * `typeName`: Name of the type (i.e. "PermitSingle").
+ /// * `abiEncodedData`: ABI-encoded data for the struct that is being hashed.
+ function eip712HashStruct(string calldata bindingsPath, string calldata typeName, bytes calldata abiEncodedData)
+ external
+ pure
+ returns (bytes32 typeHash);
+
+ /// Generates the hash of the canonical EIP-712 type representation.
+ /// Supports 2 different inputs:
+ /// 1. Name of the type (i.e. "Transaction"):
+ /// * requires previous binding generation with `forge bind-json`.
+ /// * bindings will be retrieved from the path configured in `foundry.toml`.
+ /// 2. String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)").
+ /// * Note: the cheatcode will output the canonical type even if the input is malformated
+ /// with the wrong order of elements or with extra whitespaces.
+ function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash);
+
+ /// Generates the hash of the canonical EIP-712 type representation.
+ /// Requires previous binding generation with `forge bind-json`.
+ /// Params:
+ /// * `bindingsPath`: path where the output of `forge bind-json` is stored.
+ /// * `typeName`: Name of the type (i.e. "Transaction").
+ function eip712HashType(string calldata bindingsPath, string calldata typeName)
+ external
+ pure
+ returns (bytes32 typeHash);
+
+ /// Generates a ready-to-sign digest of human-readable typed data following the EIP-712 standard.
+ function eip712HashTypedData(string calldata jsonData) external pure returns (bytes32 digest);
+
+ /// Returns ENS namehash for provided string.
+ function ensNamehash(string calldata name) external pure returns (bytes32);
+
+ /// Gets the label for the specified address.
+ function getLabel(address account) external view returns (string memory currentLabel);
+
+ /// Labels an address in call traces.
+ function label(address account, string calldata newLabel) external;
+
+ /// Pauses collection of call traces. Useful in cases when you want to skip tracing of
+ /// complex calls which are not useful for debugging.
+ function pauseTracing() external view;
+
+ /// Returns a random `address`.
+ function randomAddress() external view returns (address);
+
+ /// Returns a random `bool`.
+ function randomBool() external view returns (bool);
+
+ /// Returns a random byte array value of the given length.
+ function randomBytes(uint256 len) external view returns (bytes memory);
+
+ /// Returns a random fixed-size byte array of length 4.
+ function randomBytes4() external view returns (bytes4);
+
+ /// Returns a random fixed-size byte array of length 8.
+ function randomBytes8() external view returns (bytes8);
+
+ /// Returns a random `int256` value.
+ function randomInt() external view returns (int256);
+
+ /// Returns a random `int256` value of given bits.
+ function randomInt(uint256 bits) external view returns (int256);
+
+ /// Returns a random uint256 value.
+ function randomUint() external view returns (uint256);
+
+ /// Returns random uint256 value between the provided range (=min..=max).
+ function randomUint(uint256 min, uint256 max) external view returns (uint256);
+
+ /// Returns a random `uint256` value of given bits.
+ function randomUint(uint256 bits) external view returns (uint256);
+
+ /// Unpauses collection of call traces.
+ function resumeTracing() external view;
+
+ /// Utility cheatcode to set arbitrary storage for given target address.
+ function setArbitraryStorage(address target) external;
+
+ /// Utility cheatcode to set arbitrary storage for given target address and overwrite
+ /// any storage slots that have been previously set.
+ function setArbitraryStorage(address target, bool overwrite) external;
+
+ /// Set RNG seed.
+ function setSeed(uint256 seed) external;
+
+ /// Randomly shuffles an array.
+ function shuffle(uint256[] calldata array) external returns (uint256[] memory);
+
+ /// Sorts an array in ascending order.
+ function sort(uint256[] calldata array) external returns (uint256[] memory);
+
+ /// Encodes a `bytes` value to a base64url string.
+ function toBase64URL(bytes calldata data) external pure returns (string memory);
+
+ /// Encodes a `string` value to a base64url string.
+ function toBase64URL(string calldata data) external pure returns (string memory);
+
+ /// Encodes a `bytes` value to a base64 string.
+ function toBase64(bytes calldata data) external pure returns (string memory);
+
+ /// Encodes a `string` value to a base64 string.
+ function toBase64(string calldata data) external pure returns (string memory);
+}
+
+/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
+/// in tests, but it is not recommended to use these cheats in scripts.
+interface Vm is VmSafe {
+ // ======== EVM ========
+
+ /// Utility cheatcode to set an EIP-2930 access list for all subsequent transactions.
+ function accessList(AccessListItem[] calldata access) external;
+
+ /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.
+ function activeFork() external view returns (uint256 forkId);
+
+ /// In forking mode, explicitly grant the given address cheatcode access.
+ function allowCheatcodes(address account) external;
+
+ /// Sets `block.blobbasefee`
+ function blobBaseFee(uint256 newBlobBaseFee) external;
+
+ /// Sets the blobhashes in the transaction.
+ /// Not available on EVM versions before Cancun.
+ /// If used on unsupported EVM versions it will revert.
+ function blobhashes(bytes32[] calldata hashes) external;
+
+ /// Sets `block.chainid`.
+ function chainId(uint256 newChainId) external;
+
+ /// Clears all mocked calls.
+ function clearMockedCalls() external;
+
+ /// Clones a source account code, state, balance and nonce to a target account and updates in-memory EVM state.
+ function cloneAccount(address source, address target) external;
+
+ /// Sets `block.coinbase`.
+ function coinbase(address newCoinbase) external;
+
+ /// Marks the slots of an account and the account address as cold.
+ function cool(address target) external;
+
+ /// Utility cheatcode to mark specific storage slot as cold, simulating no prior read.
+ function coolSlot(address target, bytes32 slot) external;
+
+ /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork.
+ function createFork(string calldata urlOrAlias) external returns (uint256 forkId);
+
+ /// Creates a new fork with the given endpoint and block and returns the identifier of the fork.
+ function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
+
+ /// Creates a new fork with the given endpoint and at the block the given transaction was mined in,
+ /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork.
+ function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
+
+ /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork.
+ function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);
+
+ /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork.
+ function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
+
+ /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in,
+ /// replays all transaction mined in the block before the transaction, returns the identifier of the fork.
+ function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
+
+ /// Sets an address' balance.
+ function deal(address account, uint256 newBalance) external;
+
+ /// Removes the snapshot with the given ID created by `snapshot`.
+ /// Takes the snapshot ID to delete.
+ /// Returns `true` if the snapshot was successfully deleted.
+ /// Returns `false` if the snapshot does not exist.
+ function deleteStateSnapshot(uint256 snapshotId) external returns (bool success);
+
+ /// Removes _all_ snapshots previously created by `snapshot`.
+ function deleteStateSnapshots() external;
+
+ /// Sets `block.difficulty`.
+ /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead.
+ /// Reverts if used on unsupported EVM versions.
+ function difficulty(uint256 newDifficulty) external;
+
+ /// Dump a genesis JSON file's `allocs` to disk.
+ function dumpState(string calldata pathToStateJson) external;
+
+ /// Sets an address' code.
+ function etch(address target, bytes calldata newRuntimeBytecode) external;
+
+ /// Sets `block.basefee`.
+ function fee(uint256 newBasefee) external;
+
+ /// Gets the blockhashes from the current transaction.
+ /// Not available on EVM versions before Cancun.
+ /// If used on unsupported EVM versions it will revert.
+ function getBlobhashes() external view returns (bytes32[] memory hashes);
+
+ /// Returns true if the account is marked as persistent.
+ function isPersistent(address account) external view returns (bool persistent);
+
+ /// Load a genesis JSON file's `allocs` into the in-memory EVM state.
+ function loadAllocs(string calldata pathToAllocsJson) external;
+
+ /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
+ /// Meaning, changes made to the state of this account will be kept when switching forks.
+ function makePersistent(address account) external;
+
+ /// See `makePersistent(address)`.
+ function makePersistent(address account0, address account1) external;
+
+ /// See `makePersistent(address)`.
+ function makePersistent(address account0, address account1, address account2) external;
+
+ /// See `makePersistent(address)`.
+ function makePersistent(address[] calldata accounts) external;
+
+ /// Reverts a call to an address with specified revert data.
+ function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external;
+
+ /// Reverts a call to an address with a specific `msg.value`, with specified revert data.
+ function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData)
+ external;
+
+ /// Reverts a call to an address with specified revert data.
+ /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.
+ function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external;
+
+ /// Reverts a call to an address with a specific `msg.value`, with specified revert data.
+ /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.
+ function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) external;
+
+ /// Mocks a call to an address, returning specified data.
+ /// Calldata can either be strict or a partial match, e.g. if you only
+ /// pass a Solidity selector to the expected calldata, then the entire Solidity
+ /// function will be mocked.
+ function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;
+
+ /// Mocks a call to an address with a specific `msg.value`, returning specified data.
+ /// Calldata match takes precedence over `msg.value` in case of ambiguity.
+ function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;
+
+ /// Mocks a call to an address, returning specified data.
+ /// Calldata can either be strict or a partial match, e.g. if you only
+ /// pass a Solidity selector to the expected calldata, then the entire Solidity
+ /// function will be mocked.
+ /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.
+ function mockCall(address callee, bytes4 data, bytes calldata returnData) external;
+
+ /// Mocks a call to an address with a specific `msg.value`, returning specified data.
+ /// Calldata match takes precedence over `msg.value` in case of ambiguity.
+ /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.
+ function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external;
+
+ /// Mocks multiple calls to an address, returning specified data for each call.
+ function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external;
+
+ /// Mocks multiple calls to an address with a specific `msg.value`, returning specified data for each call.
+ function mockCalls(address callee, uint256 msgValue, bytes calldata data, bytes[] calldata returnData) external;
+
+ /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls
+ /// `target` with the same calldata. This functionality is similar to a delegate call made to
+ /// `target` contract from `callee`.
+ /// Can be used to substitute a call to a function with another implementation that captures
+ /// the primary logic of the original function but is easier to reason about.
+ /// If calldata is not a strict match then partial match by selector is attempted.
+ function mockFunction(address callee, address target, bytes calldata data) external;
+
+ /// Utility cheatcode to remove any EIP-2930 access list set by `accessList` cheatcode.
+ function noAccessList() external;
+
+ /// Sets the *next* call's `msg.sender` to be the input address.
+ function prank(address msgSender) external;
+
+ /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.
+ function prank(address msgSender, address txOrigin) external;
+
+ /// Sets the *next* delegate call's `msg.sender` to be the input address.
+ function prank(address msgSender, bool delegateCall) external;
+
+ /// Sets the *next* delegate call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.
+ function prank(address msgSender, address txOrigin, bool delegateCall) external;
+
+ /// Sets `block.prevrandao`.
+ /// Not available on EVM versions before Paris. Use `difficulty` instead.
+ /// If used on unsupported EVM versions it will revert.
+ function prevrandao(bytes32 newPrevrandao) external;
+
+ /// Sets `block.prevrandao`.
+ /// Not available on EVM versions before Paris. Use `difficulty` instead.
+ /// If used on unsupported EVM versions it will revert.
+ function prevrandao(uint256 newPrevrandao) external;
+
+ /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification.
+ function readCallers() external view returns (CallerMode callerMode, address msgSender, address txOrigin);
+
+ /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts.
+ function resetNonce(address account) external;
+
+ /// Revert the state of the EVM to a previous snapshot
+ /// Takes the snapshot ID to revert to.
+ /// Returns `true` if the snapshot was successfully reverted.
+ /// Returns `false` if the snapshot does not exist.
+ /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteStateSnapshot`.
+ function revertToState(uint256 snapshotId) external returns (bool success);
+
+ /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots
+ /// Takes the snapshot ID to revert to.
+ /// Returns `true` if the snapshot was successfully reverted and deleted.
+ /// Returns `false` if the snapshot does not exist.
+ function revertToStateAndDelete(uint256 snapshotId) external returns (bool success);
+
+ /// Revokes persistent status from the address, previously added via `makePersistent`.
+ function revokePersistent(address account) external;
+
+ /// See `revokePersistent(address)`.
+ function revokePersistent(address[] calldata accounts) external;
+
+ /// Sets `block.height`.
+ function roll(uint256 newHeight) external;
+
+ /// Updates the currently active fork to given block number
+ /// This is similar to `roll` but for the currently active fork.
+ function rollFork(uint256 blockNumber) external;
+
+ /// Updates the currently active fork to given transaction. This will `rollFork` with the number
+ /// of the block the transaction was mined in and replays all transaction mined before it in the block.
+ function rollFork(bytes32 txHash) external;
+
+ /// Updates the given fork to given block number.
+ function rollFork(uint256 forkId, uint256 blockNumber) external;
+
+ /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block.
+ function rollFork(uint256 forkId, bytes32 txHash) external;
+
+ /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
+ function selectFork(uint256 forkId) external;
+
+ /// Set blockhash for the current block.
+ /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`.
+ function setBlockhash(uint256 blockNumber, bytes32 blockHash) external;
+
+ /// Sets the nonce of an account. Must be higher than the current nonce of the account.
+ function setNonce(address account, uint64 newNonce) external;
+
+ /// Sets the nonce of an account to an arbitrary value.
+ function setNonceUnsafe(address account, uint64 newNonce) external;
+
+ /// Snapshot capture the gas usage of the last call by name from the callee perspective.
+ function snapshotGasLastCall(string calldata name) external returns (uint256 gasUsed);
+
+ /// Snapshot capture the gas usage of the last call by name in a group from the callee perspective.
+ function snapshotGasLastCall(string calldata group, string calldata name) external returns (uint256 gasUsed);
+
+ /// Snapshot the current state of the evm.
+ /// Returns the ID of the snapshot that was created.
+ /// To revert a snapshot use `revertToState`.
+ function snapshotState() external returns (uint256 snapshotId);
+
+ /// Snapshot capture an arbitrary numerical value by name.
+ /// The group name is derived from the contract name.
+ function snapshotValue(string calldata name, uint256 value) external;
+
+ /// Snapshot capture an arbitrary numerical value by name in a group.
+ function snapshotValue(string calldata group, string calldata name, uint256 value) external;
+
+ /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called.
+ function startPrank(address msgSender) external;
+
+ /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.
+ function startPrank(address msgSender, address txOrigin) external;
+
+ /// Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called.
+ function startPrank(address msgSender, bool delegateCall) external;
+
+ /// Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.
+ function startPrank(address msgSender, address txOrigin, bool delegateCall) external;
+
+ /// Start a snapshot capture of the current gas usage by name.
+ /// The group name is derived from the contract name.
+ function startSnapshotGas(string calldata name) external;
+
+ /// Start a snapshot capture of the current gas usage by name in a group.
+ function startSnapshotGas(string calldata group, string calldata name) external;
+
+ /// Resets subsequent calls' `msg.sender` to be `address(this)`.
+ function stopPrank() external;
+
+ /// Stop the snapshot capture of the current gas by latest snapshot name, capturing the gas used since the start.
+ function stopSnapshotGas() external returns (uint256 gasUsed);
+
+ /// Stop the snapshot capture of the current gas usage by name, capturing the gas used since the start.
+ /// The group name is derived from the contract name.
+ function stopSnapshotGas(string calldata name) external returns (uint256 gasUsed);
+
+ /// Stop the snapshot capture of the current gas usage by name in a group, capturing the gas used since the start.
+ function stopSnapshotGas(string calldata group, string calldata name) external returns (uint256 gasUsed);
+
+ /// Stores a value to an address' storage slot.
+ function store(address target, bytes32 slot, bytes32 value) external;
+
+ /// Fetches the given transaction from the active fork and executes it on the current state.
+ function transact(bytes32 txHash) external;
+
+ /// Fetches the given transaction from the given fork and executes it on the current state.
+ function transact(uint256 forkId, bytes32 txHash) external;
+
+ /// Sets `tx.gasprice`.
+ function txGasPrice(uint256 newGasPrice) external;
+
+ /// Utility cheatcode to mark specific storage slot as warm, simulating a prior read.
+ function warmSlot(address target, bytes32 slot) external;
+
+ /// Sets `block.timestamp`.
+ function warp(uint256 newTimestamp) external;
+
+ /// `deleteSnapshot` is being deprecated in favor of `deleteStateSnapshot`. It will be removed in future versions.
+ function deleteSnapshot(uint256 snapshotId) external returns (bool success);
+
+ /// `deleteSnapshots` is being deprecated in favor of `deleteStateSnapshots`. It will be removed in future versions.
+ function deleteSnapshots() external;
+
+ /// `revertToAndDelete` is being deprecated in favor of `revertToStateAndDelete`. It will be removed in future versions.
+ function revertToAndDelete(uint256 snapshotId) external returns (bool success);
+
+ /// `revertTo` is being deprecated in favor of `revertToState`. It will be removed in future versions.
+ function revertTo(uint256 snapshotId) external returns (bool success);
+
+ /// `snapshot` is being deprecated in favor of `snapshotState`. It will be removed in future versions.
+ function snapshot() external returns (uint256 snapshotId);
+
+ // ======== Testing ========
+
+ /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
+ function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;
+
+ /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
+ function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count)
+ external;
+
+ /// Expects a call to an address with the specified calldata.
+ /// Calldata can either be a strict or a partial match.
+ function expectCall(address callee, bytes calldata data) external;
+
+ /// Expects given number of calls to an address with the specified calldata.
+ function expectCall(address callee, bytes calldata data, uint64 count) external;
+
+ /// Expects a call to an address with the specified `msg.value` and calldata.
+ function expectCall(address callee, uint256 msgValue, bytes calldata data) external;
+
+ /// Expects given number of calls to an address with the specified `msg.value` and calldata.
+ function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external;
+
+ /// Expect a call to an address with the specified `msg.value`, gas, and calldata.
+ function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;
+
+ /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata.
+ function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external;
+
+ /// Expects the deployment of the specified bytecode by the specified address using the CREATE opcode
+ function expectCreate(bytes calldata bytecode, address deployer) external;
+
+ /// Expects the deployment of the specified bytecode by the specified address using the CREATE2 opcode
+ function expectCreate2(bytes calldata bytecode, address deployer) external;
+
+ /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
+ /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
+ function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData)
+ external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmitAnonymous(
+ bool checkTopic0,
+ bool checkTopic1,
+ bool checkTopic2,
+ bool checkTopic3,
+ bool checkData,
+ address emitter
+ ) external;
+
+ /// Prepare an expected anonymous log with all topic and data checks enabled.
+ /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data.
+ function expectEmitAnonymous() external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmitAnonymous(address emitter) external;
+
+ /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
+ /// Call this function, then emit an event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
+ function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
+ external;
+
+ /// Prepare an expected log with all topic and data checks enabled.
+ /// Call this function, then emit an event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data.
+ function expectEmit() external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmit(address emitter) external;
+
+ /// Expect a given number of logs with the provided topics.
+ function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, uint64 count) external;
+
+ /// Expect a given number of logs from a specific emitter with the provided topics.
+ function expectEmit(
+ bool checkTopic1,
+ bool checkTopic2,
+ bool checkTopic3,
+ bool checkData,
+ address emitter,
+ uint64 count
+ ) external;
+
+ /// Expect a given number of logs with all topic and data checks enabled.
+ function expectEmit(uint64 count) external;
+
+ /// Expect a given number of logs from a specific emitter with all topic and data checks enabled.
+ function expectEmit(address emitter, uint64 count) external;
+
+ /// Expects an error on next call that starts with the revert data.
+ function expectPartialRevert(bytes4 revertData) external;
+
+ /// Expects an error on next call to reverter address, that starts with the revert data.
+ function expectPartialRevert(bytes4 revertData, address reverter) external;
+
+ /// Expects an error on next call with any revert data.
+ function expectRevert() external;
+
+ /// Expects an error on next call that exactly matches the revert data.
+ function expectRevert(bytes4 revertData) external;
+
+ /// Expects a `count` number of reverts from the upcoming calls from the reverter address that match the revert data.
+ function expectRevert(bytes4 revertData, address reverter, uint64 count) external;
+
+ /// Expects a `count` number of reverts from the upcoming calls from the reverter address that exactly match the revert data.
+ function expectRevert(bytes calldata revertData, address reverter, uint64 count) external;
+
+ /// Expects an error on next call that exactly matches the revert data.
+ function expectRevert(bytes calldata revertData) external;
+
+ /// Expects an error with any revert data on next call to reverter address.
+ function expectRevert(address reverter) external;
+
+ /// Expects an error from reverter address on next call, with any revert data.
+ function expectRevert(bytes4 revertData, address reverter) external;
+
+ /// Expects an error from reverter address on next call, that exactly matches the revert data.
+ function expectRevert(bytes calldata revertData, address reverter) external;
+
+ /// Expects a `count` number of reverts from the upcoming calls with any revert data or reverter.
+ function expectRevert(uint64 count) external;
+
+ /// Expects a `count` number of reverts from the upcoming calls that match the revert data.
+ function expectRevert(bytes4 revertData, uint64 count) external;
+
+ /// Expects a `count` number of reverts from the upcoming calls that exactly match the revert data.
+ function expectRevert(bytes calldata revertData, uint64 count) external;
+
+ /// Expects a `count` number of reverts from the upcoming calls from the reverter address.
+ function expectRevert(address reverter, uint64 count) external;
+
+ /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other
+ /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.
+ function expectSafeMemory(uint64 min, uint64 max) external;
+
+ /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.
+ /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges
+ /// to the set.
+ function expectSafeMemoryCall(uint64 min, uint64 max) external;
+
+ /// Marks a test as skipped. Must be called at the top level of a test.
+ function skip(bool skipTest) external;
+
+ /// Marks a test as skipped with a reason. Must be called at the top level of a test.
+ function skip(bool skipTest, string calldata reason) external;
+
+ /// Stops all safe memory expectation in the current subcontext.
+ function stopExpectSafeMemory() external;
+
+ // ======== Utilities ========
+
+ /// Causes the next contract creation (via new) to fail and return its initcode in the returndata buffer.
+ /// This allows type-safe access to the initcode payload that would be used for contract creation.
+ /// Example usage:
+ /// vm.interceptInitcode();
+ /// bytes memory initcode;
+ /// try new MyContract(param1, param2) { assert(false); }
+ /// catch (bytes memory interceptedInitcode) { initcode = interceptedInitcode; }
+ function interceptInitcode() external;
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/console.sol b/lib/signals-implicit-mode/lib/forge-std/src/console.sol
new file mode 100644
index 000000000..4fdb6679e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/console.sol
@@ -0,0 +1,1560 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.4.22 <0.9.0;
+
+library console {
+ address constant CONSOLE_ADDRESS =
+ 0x000000000000000000636F6e736F6c652e6c6f67;
+
+ function _sendLogPayloadImplementation(bytes memory payload) internal view {
+ address consoleAddress = CONSOLE_ADDRESS;
+ /// @solidity memory-safe-assembly
+ assembly {
+ pop(
+ staticcall(
+ gas(),
+ consoleAddress,
+ add(payload, 32),
+ mload(payload),
+ 0,
+ 0
+ )
+ )
+ }
+ }
+
+ function _castToPure(
+ function(bytes memory) internal view fnIn
+ ) internal pure returns (function(bytes memory) pure fnOut) {
+ assembly {
+ fnOut := fnIn
+ }
+ }
+
+ function _sendLogPayload(bytes memory payload) internal pure {
+ _castToPure(_sendLogPayloadImplementation)(payload);
+ }
+
+ function log() internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log()"));
+ }
+
+ function logInt(int256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
+ }
+
+ function logUint(uint256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
+ }
+
+ function logString(string memory p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
+ }
+
+ function logBool(bool p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
+ }
+
+ function logAddress(address p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
+ }
+
+ function logBytes(bytes memory p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
+ }
+
+ function logBytes1(bytes1 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
+ }
+
+ function logBytes2(bytes2 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
+ }
+
+ function logBytes3(bytes3 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
+ }
+
+ function logBytes4(bytes4 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
+ }
+
+ function logBytes5(bytes5 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
+ }
+
+ function logBytes6(bytes6 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
+ }
+
+ function logBytes7(bytes7 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
+ }
+
+ function logBytes8(bytes8 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
+ }
+
+ function logBytes9(bytes9 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
+ }
+
+ function logBytes10(bytes10 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
+ }
+
+ function logBytes11(bytes11 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
+ }
+
+ function logBytes12(bytes12 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
+ }
+
+ function logBytes13(bytes13 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
+ }
+
+ function logBytes14(bytes14 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
+ }
+
+ function logBytes15(bytes15 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
+ }
+
+ function logBytes16(bytes16 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
+ }
+
+ function logBytes17(bytes17 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
+ }
+
+ function logBytes18(bytes18 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
+ }
+
+ function logBytes19(bytes19 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
+ }
+
+ function logBytes20(bytes20 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
+ }
+
+ function logBytes21(bytes21 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
+ }
+
+ function logBytes22(bytes22 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
+ }
+
+ function logBytes23(bytes23 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
+ }
+
+ function logBytes24(bytes24 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
+ }
+
+ function logBytes25(bytes25 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
+ }
+
+ function logBytes26(bytes26 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
+ }
+
+ function logBytes27(bytes27 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
+ }
+
+ function logBytes28(bytes28 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
+ }
+
+ function logBytes29(bytes29 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
+ }
+
+ function logBytes30(bytes30 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
+ }
+
+ function logBytes31(bytes31 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
+ }
+
+ function logBytes32(bytes32 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
+ }
+
+ function log(uint256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
+ }
+
+ function log(int256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
+ }
+
+ function log(string memory p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
+ }
+
+ function log(bool p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
+ }
+
+ function log(address p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
+ }
+
+ function log(uint256 p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
+ }
+
+ function log(uint256 p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
+ }
+
+ function log(uint256 p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
+ }
+
+ function log(uint256 p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
+ }
+
+ function log(string memory p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
+ }
+
+ function log(string memory p0, int256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
+ }
+
+ function log(string memory p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
+ }
+
+ function log(string memory p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
+ }
+
+ function log(string memory p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
+ }
+
+ function log(bool p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
+ }
+
+ function log(bool p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
+ }
+
+ function log(bool p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
+ }
+
+ function log(bool p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
+ }
+
+ function log(address p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
+ }
+
+ function log(address p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
+ }
+
+ function log(address p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
+ }
+
+ function log(address p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/console2.sol b/lib/signals-implicit-mode/lib/forge-std/src/console2.sol
new file mode 100644
index 000000000..03531d91d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/console2.sol
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.4.22 <0.9.0;
+
+import {console as console2} from "./console.sol";
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC1155.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC1155.sol
new file mode 100644
index 000000000..ffc82984a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC1155.sol
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import {IERC165} from "./IERC165.sol";
+
+/// @title ERC-1155 Multi Token Standard
+/// @dev See https://eips.ethereum.org/EIPS/eip-1155
+/// Note: The ERC-165 identifier for this interface is 0xd9b67a26.
+interface IERC1155 is IERC165 {
+ /// @dev
+ /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
+ /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
+ /// - The `_from` argument MUST be the address of the holder whose balance is decreased.
+ /// - The `_to` argument MUST be the address of the recipient whose balance is increased.
+ /// - The `_id` argument MUST be the token type being transferred.
+ /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
+ /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
+ /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
+ event TransferSingle(
+ address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value
+ );
+
+ /// @dev
+ /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
+ /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
+ /// - The `_from` argument MUST be the address of the holder whose balance is decreased.
+ /// - The `_to` argument MUST be the address of the recipient whose balance is increased.
+ /// - The `_ids` argument MUST be the list of tokens being transferred.
+ /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by.
+ /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
+ /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
+ event TransferBatch(
+ address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values
+ );
+
+ /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled).
+ event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
+
+ /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986.
+ /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
+ event URI(string _value, uint256 indexed _id);
+
+ /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
+ /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
+ /// - MUST revert if `_to` is the zero address.
+ /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
+ /// - MUST revert on any other error.
+ /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).
+ /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
+ /// @param _from Source address
+ /// @param _to Target address
+ /// @param _id ID of the token type
+ /// @param _value Transfer amount
+ /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
+ function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
+
+ /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call).
+ /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
+ /// - MUST revert if `_to` is the zero address.
+ /// - MUST revert if length of `_ids` is not the same as length of `_values`.
+ /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
+ /// - MUST revert on any other error.
+ /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).
+ /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
+ /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
+ /// @param _from Source address
+ /// @param _to Target address
+ /// @param _ids IDs of each token type (order and length must match _values array)
+ /// @param _values Transfer amounts per token type (order and length must match _ids array)
+ /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
+ function safeBatchTransferFrom(
+ address _from,
+ address _to,
+ uint256[] calldata _ids,
+ uint256[] calldata _values,
+ bytes calldata _data
+ ) external;
+
+ /// @notice Get the balance of an account's tokens.
+ /// @param _owner The address of the token holder
+ /// @param _id ID of the token
+ /// @return The _owner's balance of the token type requested
+ function balanceOf(address _owner, uint256 _id) external view returns (uint256);
+
+ /// @notice Get the balance of multiple account/token pairs
+ /// @param _owners The addresses of the token holders
+ /// @param _ids ID of the tokens
+ /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair)
+ function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids)
+ external
+ view
+ returns (uint256[] memory);
+
+ /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
+ /// @dev MUST emit the ApprovalForAll event on success.
+ /// @param _operator Address to add to the set of authorized operators
+ /// @param _approved True if the operator is approved, false to revoke approval
+ function setApprovalForAll(address _operator, bool _approved) external;
+
+ /// @notice Queries the approval status of an operator for a given owner.
+ /// @param _owner The owner of the tokens
+ /// @param _operator Address of authorized operator
+ /// @return True if the operator is approved, false if not
+ function isApprovedForAll(address _owner, address _operator) external view returns (bool);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC165.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC165.sol
new file mode 100644
index 000000000..9af4bf800
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC165.sol
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+interface IERC165 {
+ /// @notice Query if a contract implements an interface
+ /// @param interfaceID The interface identifier, as specified in ERC-165
+ /// @dev Interface identification is specified in ERC-165. This function
+ /// uses less than 30,000 gas.
+ /// @return `true` if the contract implements `interfaceID` and
+ /// `interfaceID` is not 0xffffffff, `false` otherwise
+ function supportsInterface(bytes4 interfaceID) external view returns (bool);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC20.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC20.sol
new file mode 100644
index 000000000..ba40806c3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC20.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+/// @dev Interface of the ERC20 standard as defined in the EIP.
+/// @dev This includes the optional name, symbol, and decimals metadata.
+interface IERC20 {
+ /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
+ event Transfer(address indexed from, address indexed to, uint256 value);
+
+ /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
+ /// is the new allowance.
+ event Approval(address indexed owner, address indexed spender, uint256 value);
+
+ /// @notice Returns the amount of tokens in existence.
+ function totalSupply() external view returns (uint256);
+
+ /// @notice Returns the amount of tokens owned by `account`.
+ function balanceOf(address account) external view returns (uint256);
+
+ /// @notice Moves `amount` tokens from the caller's account to `to`.
+ function transfer(address to, uint256 amount) external returns (bool);
+
+ /// @notice Returns the remaining number of tokens that `spender` is allowed
+ /// to spend on behalf of `owner`
+ function allowance(address owner, address spender) external view returns (uint256);
+
+ /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
+ /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+ function approve(address spender, uint256 amount) external returns (bool);
+
+ /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
+ /// `amount` is then deducted from the caller's allowance.
+ function transferFrom(address from, address to, uint256 amount) external returns (bool);
+
+ /// @notice Returns the name of the token.
+ function name() external view returns (string memory);
+
+ /// @notice Returns the symbol of the token.
+ function symbol() external view returns (string memory);
+
+ /// @notice Returns the decimals places of the token.
+ function decimals() external view returns (uint8);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC4626.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC4626.sol
new file mode 100644
index 000000000..c645a0fec
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC4626.sol
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import {IERC20} from "./IERC20.sol";
+
+/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
+/// https://eips.ethereum.org/EIPS/eip-4626
+interface IERC4626 is IERC20 {
+ event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
+
+ event Withdraw(
+ address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
+ );
+
+ /// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
+ /// @dev
+ /// - MUST be an ERC-20 token contract.
+ /// - MUST NOT revert.
+ function asset() external view returns (address assetTokenAddress);
+
+ /// @notice Returns the total amount of the underlying asset that is “managed” by Vault.
+ /// @dev
+ /// - SHOULD include any compounding that occurs from yield.
+ /// - MUST be inclusive of any fees that are charged against assets in the Vault.
+ /// - MUST NOT revert.
+ function totalAssets() external view returns (uint256 totalManagedAssets);
+
+ /// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
+ /// scenario where all the conditions are met.
+ /// @dev
+ /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
+ /// - MUST NOT show any variations depending on the caller.
+ /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
+ /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
+ /// from.
+ function convertToShares(uint256 assets) external view returns (uint256 shares);
+
+ /// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
+ /// scenario where all the conditions are met.
+ /// @dev
+ /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
+ /// - MUST NOT show any variations depending on the caller.
+ /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
+ /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
+ /// from.
+ function convertToAssets(uint256 shares) external view returns (uint256 assets);
+
+ /// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
+ /// through a deposit call.
+ /// @dev
+ /// - MUST return a limited value if receiver is subject to some deposit limit.
+ /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
+ /// - MUST NOT revert.
+ function maxDeposit(address receiver) external view returns (uint256 maxAssets);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
+ /// current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
+ /// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
+ /// in the same transaction.
+ /// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
+ /// deposit would be accepted, regardless if the user has enough tokens approved, etc.
+ /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by depositing.
+ function previewDeposit(uint256 assets) external view returns (uint256 shares);
+
+ /// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
+ /// @dev
+ /// - MUST emit the Deposit event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ /// deposit execution, and are accounted for during deposit.
+ /// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
+ /// approving enough underlying tokens to the Vault contract, etc).
+ ///
+ /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
+ function deposit(uint256 assets, address receiver) external returns (uint256 shares);
+
+ /// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
+ /// @dev
+ /// - MUST return a limited value if receiver is subject to some mint limit.
+ /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
+ /// - MUST NOT revert.
+ function maxMint(address receiver) external view returns (uint256 maxShares);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
+ /// current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
+ /// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
+ /// same transaction.
+ /// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
+ /// would be accepted, regardless if the user has enough tokens approved, etc.
+ /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by minting.
+ function previewMint(uint256 shares) external view returns (uint256 assets);
+
+ /// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
+ /// @dev
+ /// - MUST emit the Deposit event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
+ /// execution, and are accounted for during mint.
+ /// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
+ /// approving enough underlying tokens to the Vault contract, etc).
+ ///
+ /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
+ function mint(uint256 shares, address receiver) external returns (uint256 assets);
+
+ /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
+ /// Vault, through a withdrawal call.
+ /// @dev
+ /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
+ /// - MUST NOT revert.
+ function maxWithdraw(address owner) external view returns (uint256 maxAssets);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
+ /// given current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
+ /// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
+ /// called
+ /// in the same transaction.
+ /// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
+ /// the withdrawal would be accepted, regardless if the user has enough shares, etc.
+ /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by depositing.
+ function previewWithdraw(uint256 assets) external view returns (uint256 shares);
+
+ /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver.
+ /// @dev
+ /// - MUST emit the Withdraw event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ /// withdraw execution, and are accounted for during withdrawal.
+ /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
+ /// not having enough shares, etc).
+ ///
+ /// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
+ /// Those methods should be performed separately.
+ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
+
+ /// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
+ /// through a redeem call.
+ /// @dev
+ /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
+ /// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
+ /// - MUST NOT revert.
+ function maxRedeem(address owner) external view returns (uint256 maxShares);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
+ /// given current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
+ /// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
+ /// same transaction.
+ /// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
+ /// redemption would be accepted, regardless if the user has enough shares, etc.
+ /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by redeeming.
+ function previewRedeem(uint256 shares) external view returns (uint256 assets);
+
+ /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver.
+ /// @dev
+ /// - MUST emit the Withdraw event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ /// redeem execution, and are accounted for during redeem.
+ /// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
+ /// not having enough shares, etc).
+ ///
+ /// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
+ /// Those methods should be performed separately.
+ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC6909.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC6909.sol
new file mode 100644
index 000000000..6e11cb460
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC6909.sol
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import {IERC165} from "./IERC165.sol";
+
+/// @dev Required interface of an ERC-6909 compliant contract, as defined in
+/// https://eips.ethereum.org/EIPS/eip-6909
+interface IERC6909 is IERC165 {
+ /// @dev Emitted when the allowance of a `spender` for an `owner` is set for a token of type `id`.
+ event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
+
+ /// @dev Emitted when `owner` grants or revokes operator status for a `spender`.
+ event OperatorSet(address indexed owner, address indexed spender, bool approved);
+
+ /// @dev Emitted when `amount` tokens of type `id` are moved from `sender` to `receiver` initiated by `caller`.
+ event Transfer(
+ address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount
+ );
+
+ ///@dev Returns the amount of tokens of type `id` owned by `owner`.
+ function balanceOf(address owner, uint256 id) external view returns (uint256);
+
+ /// @dev Returns the amount of tokens of type `id` that `spender` is allowed to spend on behalf of `owner`.
+ /// NOTE: Does not include operator allowances.
+ function allowance(address owner, address spender, uint256 id) external view returns (uint256);
+
+ /// @dev Returns true if `spender` is set as an operator for `owner`.
+ function isOperator(address owner, address spender) external view returns (bool);
+
+ /// @dev Sets an approval to `spender` for `amount` tokens of type `id` from the caller's tokens.
+ /// Must return true.
+ function approve(address spender, uint256 id, uint256 amount) external returns (bool);
+
+ /// @dev Grants or revokes unlimited transfer permission of any token id to `spender` for the caller's tokens.
+ /// Must return true.
+ function setOperator(address spender, bool approved) external returns (bool);
+
+ /// @dev Transfers `amount` of token type `id` from the caller's account to `receiver`.
+ /// Must return true.
+ function transfer(address receiver, uint256 id, uint256 amount) external returns (bool);
+
+ /// @dev Transfers `amount` of token type `id` from `sender` to `receiver`.
+ /// Must return true.
+ function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool);
+}
+
+/// @dev Optional extension of {IERC6909} that adds metadata functions.
+interface IERC6909Metadata is IERC6909 {
+ /// @dev Returns the name of the token of type `id`.
+ function name(uint256 id) external view returns (string memory);
+
+ /// @dev Returns the ticker symbol of the token of type `id`.
+ function symbol(uint256 id) external view returns (string memory);
+
+ /// @dev Returns the number of decimals for the token of type `id`.
+ function decimals(uint256 id) external view returns (uint8);
+}
+
+/// @dev Optional extension of {IERC6909} that adds content URI functions.
+interface IERC6909ContentURI is IERC6909 {
+ /// @dev Returns URI for the contract.
+ function contractURI() external view returns (string memory);
+
+ /// @dev Returns the URI for the token of type `id`.
+ function tokenURI(uint256 id) external view returns (string memory);
+}
+
+/// @dev Optional extension of {IERC6909} that adds a token supply function.
+interface IERC6909TokenSupply is IERC6909 {
+ /// @dev Returns the total supply of the token of type `id`.
+ function totalSupply(uint256 id) external view returns (uint256);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC721.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC721.sol
new file mode 100644
index 000000000..21a4a94de
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC721.sol
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import {IERC165} from "./IERC165.sol";
+
+/// @title ERC-721 Non-Fungible Token Standard
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
+interface IERC721 is IERC165 {
+ /// @dev This emits when ownership of any NFT changes by any mechanism.
+ /// This event emits when NFTs are created (`from` == 0) and destroyed
+ /// (`to` == 0). Exception: during contract creation, any number of NFTs
+ /// may be created and assigned without emitting Transfer. At the time of
+ /// any transfer, the approved address for that NFT (if any) is reset to none.
+ event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
+
+ /// @dev This emits when the approved address for an NFT is changed or
+ /// reaffirmed. The zero address indicates there is no approved address.
+ /// When a Transfer event emits, this also indicates that the approved
+ /// address for that NFT (if any) is reset to none.
+ event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
+
+ /// @dev This emits when an operator is enabled or disabled for an owner.
+ /// The operator can manage all NFTs of the owner.
+ event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
+
+ /// @notice Count all NFTs assigned to an owner
+ /// @dev NFTs assigned to the zero address are considered invalid, and this
+ /// function throws for queries about the zero address.
+ /// @param _owner An address for whom to query the balance
+ /// @return The number of NFTs owned by `_owner`, possibly zero
+ function balanceOf(address _owner) external view returns (uint256);
+
+ /// @notice Find the owner of an NFT
+ /// @dev NFTs assigned to zero address are considered invalid, and queries
+ /// about them do throw.
+ /// @param _tokenId The identifier for an NFT
+ /// @return The address of the owner of the NFT
+ function ownerOf(uint256 _tokenId) external view returns (address);
+
+ /// @notice Transfers the ownership of an NFT from one address to another address
+ /// @dev Throws unless `msg.sender` is the current owner, an authorized
+ /// operator, or the approved address for this NFT. Throws if `_from` is
+ /// not the current owner. Throws if `_to` is the zero address. Throws if
+ /// `_tokenId` is not a valid NFT. When transfer is complete, this function
+ /// checks if `_to` is a smart contract (code size > 0). If so, it calls
+ /// `onERC721Received` on `_to` and throws if the return value is not
+ /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
+ /// @param _from The current owner of the NFT
+ /// @param _to The new owner
+ /// @param _tokenId The NFT to transfer
+ /// @param data Additional data with no specified format, sent in call to `_to`
+ function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
+
+ /// @notice Transfers the ownership of an NFT from one address to another address
+ /// @dev This works identically to the other function with an extra data parameter,
+ /// except this function just sets data to "".
+ /// @param _from The current owner of the NFT
+ /// @param _to The new owner
+ /// @param _tokenId The NFT to transfer
+ function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
+
+ /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
+ /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
+ /// THEY MAY BE PERMANENTLY LOST
+ /// @dev Throws unless `msg.sender` is the current owner, an authorized
+ /// operator, or the approved address for this NFT. Throws if `_from` is
+ /// not the current owner. Throws if `_to` is the zero address. Throws if
+ /// `_tokenId` is not a valid NFT.
+ /// @param _from The current owner of the NFT
+ /// @param _to The new owner
+ /// @param _tokenId The NFT to transfer
+ function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
+
+ /// @notice Change or reaffirm the approved address for an NFT
+ /// @dev The zero address indicates there is no approved address.
+ /// Throws unless `msg.sender` is the current NFT owner, or an authorized
+ /// operator of the current owner.
+ /// @param _approved The new approved NFT controller
+ /// @param _tokenId The NFT to approve
+ function approve(address _approved, uint256 _tokenId) external payable;
+
+ /// @notice Enable or disable approval for a third party ("operator") to manage
+ /// all of `msg.sender`'s assets
+ /// @dev Emits the ApprovalForAll event. The contract MUST allow
+ /// multiple operators per owner.
+ /// @param _operator Address to add to the set of authorized operators
+ /// @param _approved True if the operator is approved, false to revoke approval
+ function setApprovalForAll(address _operator, bool _approved) external;
+
+ /// @notice Get the approved address for a single NFT
+ /// @dev Throws if `_tokenId` is not a valid NFT.
+ /// @param _tokenId The NFT to find the approved address for
+ /// @return The approved address for this NFT, or the zero address if there is none
+ function getApproved(uint256 _tokenId) external view returns (address);
+
+ /// @notice Query if an address is an authorized operator for another address
+ /// @param _owner The address that owns the NFTs
+ /// @param _operator The address that acts on behalf of the owner
+ /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
+ function isApprovedForAll(address _owner, address _operator) external view returns (bool);
+}
+
+/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
+interface IERC721TokenReceiver {
+ /// @notice Handle the receipt of an NFT
+ /// @dev The ERC721 smart contract calls this function on the recipient
+ /// after a `transfer`. This function MAY throw to revert and reject the
+ /// transfer. Return of other than the magic value MUST result in the
+ /// transaction being reverted.
+ /// Note: the contract address is always the message sender.
+ /// @param _operator The address which called `safeTransferFrom` function
+ /// @param _from The address which previously owned the token
+ /// @param _tokenId The NFT identifier which is being transferred
+ /// @param _data Additional data with no specified format
+ /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
+ /// unless throwing
+ function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data)
+ external
+ returns (bytes4);
+}
+
+/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
+interface IERC721Metadata is IERC721 {
+ /// @notice A descriptive name for a collection of NFTs in this contract
+ function name() external view returns (string memory _name);
+
+ /// @notice An abbreviated name for NFTs in this contract
+ function symbol() external view returns (string memory _symbol);
+
+ /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
+ /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
+ /// 3986. The URI may point to a JSON file that conforms to the "ERC721
+ /// Metadata JSON Schema".
+ function tokenURI(uint256 _tokenId) external view returns (string memory);
+}
+
+/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// Note: the ERC-165 identifier for this interface is 0x780e9d63.
+interface IERC721Enumerable is IERC721 {
+ /// @notice Count NFTs tracked by this contract
+ /// @return A count of valid NFTs tracked by this contract, where each one of
+ /// them has an assigned and queryable owner not equal to the zero address
+ function totalSupply() external view returns (uint256);
+
+ /// @notice Enumerate valid NFTs
+ /// @dev Throws if `_index` >= `totalSupply()`.
+ /// @param _index A counter less than `totalSupply()`
+ /// @return The token identifier for the `_index`th NFT,
+ /// (sort order not specified)
+ function tokenByIndex(uint256 _index) external view returns (uint256);
+
+ /// @notice Enumerate NFTs assigned to an owner
+ /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
+ /// `_owner` is the zero address, representing invalid NFTs.
+ /// @param _owner An address where we are interested in NFTs owned by them
+ /// @param _index A counter less than `balanceOf(_owner)`
+ /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
+ /// (sort order not specified)
+ function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC7540.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC7540.sol
new file mode 100644
index 000000000..91a38ca35
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC7540.sol
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import {IERC7575} from "./IERC7575.sol";
+
+/// @dev Interface of the base operator logic of ERC7540, as defined in
+/// https://eips.ethereum.org/EIPS/eip-7540
+interface IERC7540Operator {
+ /**
+ * @dev The event emitted when an operator is set.
+ *
+ * @param controller The address of the controller.
+ * @param operator The address of the operator.
+ * @param approved The approval status.
+ */
+ event OperatorSet(address indexed controller, address indexed operator, bool approved);
+
+ /**
+ * @dev Sets or removes an operator for the caller.
+ *
+ * @param operator The address of the operator.
+ * @param approved The approval status.
+ * @return Whether the call was executed successfully or not
+ */
+ function setOperator(address operator, bool approved) external returns (bool);
+
+ /**
+ * @dev Returns `true` if the `operator` is approved as an operator for an `controller`.
+ *
+ * @param controller The address of the controller.
+ * @param operator The address of the operator.
+ * @return status The approval status
+ */
+ function isOperator(address controller, address operator) external view returns (bool status);
+}
+
+/// @dev Interface of the asynchronous deposit Vault interface of ERC7540, as defined in
+/// https://eips.ethereum.org/EIPS/eip-7540
+interface IERC7540Deposit is IERC7540Operator {
+ event DepositRequest(
+ address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
+ );
+ /**
+ * @dev Transfers assets from sender into the Vault and submits a Request for asynchronous deposit.
+ *
+ * - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
+ * - MUST revert if all of assets cannot be requested for deposit.
+ * - owner MUST be msg.sender unless some unspecified explicit approval is given by the caller,
+ * approval of ERC-20 tokens from owner to sender is NOT enough.
+ *
+ * @param assets the amount of deposit assets to transfer from owner
+ * @param controller the controller of the request who will be able to operate the request
+ * @param owner the source of the deposit assets
+ *
+ * NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
+ */
+
+ function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId);
+
+ /**
+ * @dev Returns the amount of requested assets in Pending state.
+ *
+ * - MUST NOT include any assets in Claimable state for deposit or mint.
+ * - MUST NOT show any variations depending on the caller.
+ * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
+ */
+ function pendingDepositRequest(uint256 requestId, address controller)
+ external
+ view
+ returns (uint256 pendingAssets);
+
+ /**
+ * @dev Returns the amount of requested assets in Claimable state for the controller to deposit or mint.
+ *
+ * - MUST NOT include any assets in Pending state.
+ * - MUST NOT show any variations depending on the caller.
+ * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
+ */
+ function claimableDepositRequest(uint256 requestId, address controller)
+ external
+ view
+ returns (uint256 claimableAssets);
+
+ /**
+ * @dev Mints shares Vault shares to receiver by claiming the Request of the controller.
+ *
+ * - MUST emit the Deposit event.
+ * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
+ */
+ function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares);
+
+ /**
+ * @dev Mints exactly shares Vault shares to receiver by claiming the Request of the controller.
+ *
+ * - MUST emit the Deposit event.
+ * - controller MUST equal msg.sender unless the controller has approved the msg.sender as an operator.
+ */
+ function mint(uint256 shares, address receiver, address controller) external returns (uint256 assets);
+}
+
+/// @dev Interface of the asynchronous deposit Vault interface of ERC7540, as defined in
+/// https://eips.ethereum.org/EIPS/eip-7540
+interface IERC7540Redeem is IERC7540Operator {
+ event RedeemRequest(
+ address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
+ );
+
+ /**
+ * @dev Assumes control of shares from sender into the Vault and submits a Request for asynchronous redeem.
+ *
+ * - MUST support a redeem Request flow where the control of shares is taken from sender directly
+ * where msg.sender has ERC-20 approval over the shares of owner.
+ * - MUST revert if all of shares cannot be requested for redeem.
+ *
+ * @param shares the amount of shares to be redeemed to transfer from owner
+ * @param controller the controller of the request who will be able to operate the request
+ * @param owner the source of the shares to be redeemed
+ *
+ * NOTE: most implementations will require pre-approval of the Vault with the Vault's share token.
+ */
+ function requestRedeem(uint256 shares, address controller, address owner) external returns (uint256 requestId);
+
+ /**
+ * @dev Returns the amount of requested shares in Pending state.
+ *
+ * - MUST NOT include any shares in Claimable state for redeem or withdraw.
+ * - MUST NOT show any variations depending on the caller.
+ * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
+ */
+ function pendingRedeemRequest(uint256 requestId, address controller)
+ external
+ view
+ returns (uint256 pendingShares);
+
+ /**
+ * @dev Returns the amount of requested shares in Claimable state for the controller to redeem or withdraw.
+ *
+ * - MUST NOT include any shares in Pending state for redeem or withdraw.
+ * - MUST NOT show any variations depending on the caller.
+ * - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
+ */
+ function claimableRedeemRequest(uint256 requestId, address controller)
+ external
+ view
+ returns (uint256 claimableShares);
+}
+
+/// @dev Interface of the fully asynchronous Vault interface of ERC7540, as defined in
+/// https://eips.ethereum.org/EIPS/eip-7540
+interface IERC7540 is IERC7540Deposit, IERC7540Redeem, IERC7575 {}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC7575.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC7575.sol
new file mode 100644
index 000000000..207e3e7fe
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IERC7575.sol
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import {IERC165} from "./IERC165.sol";
+
+/// @dev Interface of the ERC7575 "Multi-Asset ERC-4626 Vaults", as defined in
+/// https://eips.ethereum.org/EIPS/eip-7575
+interface IERC7575 is IERC165 {
+ event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
+ event Withdraw(
+ address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
+ );
+
+ /**
+ * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
+ *
+ * - MUST be an ERC-20 token contract.
+ * - MUST NOT revert.
+ */
+ function asset() external view returns (address assetTokenAddress);
+
+ /**
+ * @dev Returns the address of the share token
+ *
+ * - MUST be an ERC-20 token contract.
+ * - MUST NOT revert.
+ */
+ function share() external view returns (address shareTokenAddress);
+
+ /**
+ * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
+ * scenario where all the conditions are met.
+ *
+ * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
+ * - MUST NOT show any variations depending on the caller.
+ * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
+ * - MUST NOT revert.
+ *
+ * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
+ * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
+ * from.
+ */
+ function convertToShares(uint256 assets) external view returns (uint256 shares);
+
+ /**
+ * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
+ * scenario where all the conditions are met.
+ *
+ * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
+ * - MUST NOT show any variations depending on the caller.
+ * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
+ * - MUST NOT revert.
+ *
+ * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
+ * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
+ * from.
+ */
+ function convertToAssets(uint256 shares) external view returns (uint256 assets);
+
+ /**
+ * @dev Returns the total amount of the underlying asset that is “managed” by Vault.
+ *
+ * - SHOULD include any compounding that occurs from yield.
+ * - MUST be inclusive of any fees that are charged against assets in the Vault.
+ * - MUST NOT revert.
+ */
+ function totalAssets() external view returns (uint256 totalManagedAssets);
+
+ /**
+ * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
+ * through a deposit call.
+ *
+ * - MUST return a limited value if receiver is subject to some deposit limit.
+ * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
+ * - MUST NOT revert.
+ */
+ function maxDeposit(address receiver) external view returns (uint256 maxAssets);
+
+ /**
+ * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
+ * current on-chain conditions.
+ *
+ * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
+ * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
+ * in the same transaction.
+ * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
+ * deposit would be accepted, regardless if the user has enough tokens approved, etc.
+ * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
+ * - MUST NOT revert.
+ *
+ * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
+ * share price or some other type of condition, meaning the depositor will lose assets by depositing.
+ */
+ function previewDeposit(uint256 assets) external view returns (uint256 shares);
+
+ /**
+ * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
+ *
+ * - MUST emit the Deposit event.
+ * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ * deposit execution, and are accounted for during deposit.
+ * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
+ * approving enough underlying tokens to the Vault contract, etc).
+ *
+ * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
+ */
+ function deposit(uint256 assets, address receiver) external returns (uint256 shares);
+
+ /**
+ * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
+ * - MUST return a limited value if receiver is subject to some mint limit.
+ * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
+ * - MUST NOT revert.
+ */
+ function maxMint(address receiver) external view returns (uint256 maxShares);
+
+ /**
+ * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
+ * current on-chain conditions.
+ *
+ * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
+ * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
+ * same transaction.
+ * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
+ * would be accepted, regardless if the user has enough tokens approved, etc.
+ * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
+ * - MUST NOT revert.
+ *
+ * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
+ * share price or some other type of condition, meaning the depositor will lose assets by minting.
+ */
+ function previewMint(uint256 shares) external view returns (uint256 assets);
+
+ /**
+ * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
+ *
+ * - MUST emit the Deposit event.
+ * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
+ * execution, and are accounted for during mint.
+ * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
+ * approving enough underlying tokens to the Vault contract, etc).
+ *
+ * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
+ */
+ function mint(uint256 shares, address receiver) external returns (uint256 assets);
+
+ /**
+ * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
+ * Vault, through a withdraw call.
+ *
+ * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
+ * - MUST NOT revert.
+ */
+ function maxWithdraw(address owner) external view returns (uint256 maxAssets);
+
+ /**
+ * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
+ * given current on-chain conditions.
+ *
+ * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
+ * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
+ * called
+ * in the same transaction.
+ * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
+ * the withdrawal would be accepted, regardless if the user has enough shares, etc.
+ * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
+ * - MUST NOT revert.
+ *
+ * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
+ * share price or some other type of condition, meaning the depositor will lose assets by depositing.
+ */
+ function previewWithdraw(uint256 assets) external view returns (uint256 shares);
+
+ /**
+ * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
+ *
+ * - MUST emit the Withdraw event.
+ * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ * withdraw execution, and are accounted for during withdraw.
+ * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
+ * not having enough shares, etc).
+ *
+ * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
+ * Those methods should be performed separately.
+ */
+ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
+
+ /**
+ * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
+ * through a redeem call.
+ *
+ * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
+ * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
+ * - MUST NOT revert.
+ */
+ function maxRedeem(address owner) external view returns (uint256 maxShares);
+
+ /**
+ * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
+ * given current on-chain conditions.
+ *
+ * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
+ * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
+ * same transaction.
+ * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
+ * redemption would be accepted, regardless if the user has enough shares, etc.
+ * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
+ * - MUST NOT revert.
+ *
+ * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
+ * share price or some other type of condition, meaning the depositor will lose assets by redeeming.
+ */
+ function previewRedeem(uint256 shares) external view returns (uint256 assets);
+
+ /**
+ * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
+ *
+ * - MUST emit the Withdraw event.
+ * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ * redeem execution, and are accounted for during redeem.
+ * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
+ * not having enough shares, etc).
+ *
+ * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
+ * Those methods should be performed separately.
+ */
+ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
+}
+
+/// @dev Interface of the ERC20 share token, as defined in
+/// https://eips.ethereum.org/EIPS/eip-7575
+interface IERC7575Share is IERC165 {
+ event VaultUpdate(address indexed asset, address vault);
+
+ /**
+ * @dev Returns the address of the Vault for the given asset.
+ *
+ * @param asset the ERC-20 token to deposit with into the Vault
+ */
+ function vault(address asset) external view returns (address);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IMulticall3.sol b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IMulticall3.sol
new file mode 100644
index 000000000..0d031b71d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/interfaces/IMulticall3.sol
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+interface IMulticall3 {
+ struct Call {
+ address target;
+ bytes callData;
+ }
+
+ struct Call3 {
+ address target;
+ bool allowFailure;
+ bytes callData;
+ }
+
+ struct Call3Value {
+ address target;
+ bool allowFailure;
+ uint256 value;
+ bytes callData;
+ }
+
+ struct Result {
+ bool success;
+ bytes returnData;
+ }
+
+ function aggregate(Call[] calldata calls)
+ external
+ payable
+ returns (uint256 blockNumber, bytes[] memory returnData);
+
+ function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
+
+ function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
+
+ function blockAndAggregate(Call[] calldata calls)
+ external
+ payable
+ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
+
+ function getBasefee() external view returns (uint256 basefee);
+
+ function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);
+
+ function getBlockNumber() external view returns (uint256 blockNumber);
+
+ function getChainId() external view returns (uint256 chainid);
+
+ function getCurrentBlockCoinbase() external view returns (address coinbase);
+
+ function getCurrentBlockDifficulty() external view returns (uint256 difficulty);
+
+ function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);
+
+ function getCurrentBlockTimestamp() external view returns (uint256 timestamp);
+
+ function getEthBalance(address addr) external view returns (uint256 balance);
+
+ function getLastBlockHash() external view returns (bytes32 blockHash);
+
+ function tryAggregate(bool requireSuccess, Call[] calldata calls)
+ external
+ payable
+ returns (Result[] memory returnData);
+
+ function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
+ external
+ payable
+ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/src/safeconsole.sol b/lib/signals-implicit-mode/lib/forge-std/src/safeconsole.sol
new file mode 100644
index 000000000..87c475a5b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/src/safeconsole.sol
@@ -0,0 +1,13937 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+/// @author philogy
+/// @dev Code generated automatically by script.
+library safeconsole {
+ uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67;
+
+ // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374)
+ // for the view-to-pure log trick.
+ function _sendLogPayload(uint256 offset, uint256 size) private pure {
+ function(uint256, uint256) internal view fnIn = _sendLogPayloadView;
+ function(uint256, uint256) internal pure pureSendLogPayload;
+ /// @solidity memory-safe-assembly
+ assembly {
+ pureSendLogPayload := fnIn
+ }
+ pureSendLogPayload(offset, size);
+ }
+
+ function _sendLogPayloadView(uint256 offset, uint256 size) private view {
+ /// @solidity memory-safe-assembly
+ assembly {
+ pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0))
+ }
+ }
+
+ function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
+ function(uint256, uint256, uint256) internal view fnIn = _memcopyView;
+ function(uint256, uint256, uint256) internal pure pureMemcopy;
+ /// @solidity memory-safe-assembly
+ assembly {
+ pureMemcopy := fnIn
+ }
+ pureMemcopy(fromOffset, toOffset, length);
+ }
+
+ function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
+ /// @solidity memory-safe-assembly
+ assembly {
+ pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length))
+ }
+ }
+
+ function logMemory(uint256 offset, uint256 length) internal pure {
+ if (offset >= 0x60) {
+ // Sufficient memory before slice to prepare call header.
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(sub(offset, 0x60))
+ m1 := mload(sub(offset, 0x40))
+ m2 := mload(sub(offset, 0x20))
+ // Selector of `log(bytes)`.
+ mstore(sub(offset, 0x60), 0x0be77f56)
+ mstore(sub(offset, 0x40), 0x20)
+ mstore(sub(offset, 0x20), length)
+ }
+ _sendLogPayload(offset - 0x44, length + 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(sub(offset, 0x60), m0)
+ mstore(sub(offset, 0x40), m1)
+ mstore(sub(offset, 0x20), m2)
+ }
+ } else {
+ // Insufficient space, so copy slice forward, add header and reverse.
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ uint256 endOffset = offset + length;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(add(endOffset, 0x00))
+ m1 := mload(add(endOffset, 0x20))
+ m2 := mload(add(endOffset, 0x40))
+ }
+ _memcopy(offset, offset + 0x60, length);
+ /// @solidity memory-safe-assembly
+ assembly {
+ // Selector of `log(bytes)`.
+ mstore(add(offset, 0x00), 0x0be77f56)
+ mstore(add(offset, 0x20), 0x20)
+ mstore(add(offset, 0x40), length)
+ }
+ _sendLogPayload(offset + 0x1c, length + 0x44);
+ _memcopy(offset + 0x60, offset, length);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(add(endOffset, 0x00), m0)
+ mstore(add(endOffset, 0x20), m1)
+ mstore(add(endOffset, 0x40), m2)
+ }
+ }
+ }
+
+ function log(address p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ // Selector of `log(address)`.
+ mstore(0x00, 0x2c2ecbc2)
+ mstore(0x20, p0)
+ }
+ _sendLogPayload(0x1c, 0x24);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ }
+ }
+
+ function log(bool p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ // Selector of `log(bool)`.
+ mstore(0x00, 0x32458eed)
+ mstore(0x20, p0)
+ }
+ _sendLogPayload(0x1c, 0x24);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ }
+ }
+
+ function log(uint256 p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ // Selector of `log(uint256)`.
+ mstore(0x00, 0xf82c50f1)
+ mstore(0x20, p0)
+ }
+ _sendLogPayload(0x1c, 0x24);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ }
+ }
+
+ function log(bytes32 p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(string)`.
+ mstore(0x00, 0x41304fac)
+ mstore(0x20, 0x20)
+ writeString(0x40, p0)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(address,address)`.
+ mstore(0x00, 0xdaf0d4aa)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(address p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(address,bool)`.
+ mstore(0x00, 0x75b605d3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(address p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(address,uint256)`.
+ mstore(0x00, 0x8309e8a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(address p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,string)`.
+ mstore(0x00, 0x759f86bb)
+ mstore(0x20, p0)
+ mstore(0x40, 0x40)
+ writeString(0x60, p1)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(bool,address)`.
+ mstore(0x00, 0x853c4849)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(bool p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(bool,bool)`.
+ mstore(0x00, 0x2a110e83)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(bool p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(bool,uint256)`.
+ mstore(0x00, 0x399174d3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(bool p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,string)`.
+ mstore(0x00, 0x8feac525)
+ mstore(0x20, p0)
+ mstore(0x40, 0x40)
+ writeString(0x60, p1)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(uint256,address)`.
+ mstore(0x00, 0x69276c86)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(uint256 p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(uint256,bool)`.
+ mstore(0x00, 0x1c9d7eb3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(uint256,uint256)`.
+ mstore(0x00, 0xf666715a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,string)`.
+ mstore(0x00, 0x643fd0df)
+ mstore(0x20, p0)
+ mstore(0x40, 0x40)
+ writeString(0x60, p1)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(string,address)`.
+ mstore(0x00, 0x319af333)
+ mstore(0x20, 0x40)
+ mstore(0x40, p1)
+ writeString(0x60, p0)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(string,bool)`.
+ mstore(0x00, 0xc3b55635)
+ mstore(0x20, 0x40)
+ mstore(0x40, p1)
+ writeString(0x60, p0)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(string,uint256)`.
+ mstore(0x00, 0xb60e72cc)
+ mstore(0x20, 0x40)
+ mstore(0x40, p1)
+ writeString(0x60, p0)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,string)`.
+ mstore(0x00, 0x4b5c4277)
+ mstore(0x20, 0x40)
+ mstore(0x40, 0x80)
+ writeString(0x60, p0)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,address,address)`.
+ mstore(0x00, 0x018c84c2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,address,bool)`.
+ mstore(0x00, 0xf2a66286)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,address,uint256)`.
+ mstore(0x00, 0x17fe6185)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,address,string)`.
+ mstore(0x00, 0x007150be)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,bool,address)`.
+ mstore(0x00, 0xf11699ed)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,bool,bool)`.
+ mstore(0x00, 0xeb830c92)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,bool,uint256)`.
+ mstore(0x00, 0x9c4f99fb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,bool,string)`.
+ mstore(0x00, 0x212255cc)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,uint256,address)`.
+ mstore(0x00, 0x7bc0d848)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,uint256,bool)`.
+ mstore(0x00, 0x678209a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,uint256,uint256)`.
+ mstore(0x00, 0xb69bcaf6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,uint256,string)`.
+ mstore(0x00, 0xa1f2e8aa)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,string,address)`.
+ mstore(0x00, 0xf08744e8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,string,bool)`.
+ mstore(0x00, 0xcf020fb1)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,string,uint256)`.
+ mstore(0x00, 0x67dd6ff1)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(address,string,string)`.
+ mstore(0x00, 0xfb772265)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p1)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bool p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,address,address)`.
+ mstore(0x00, 0xd2763667)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,address,bool)`.
+ mstore(0x00, 0x18c9c746)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,address,uint256)`.
+ mstore(0x00, 0x5f7b9afb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,address,string)`.
+ mstore(0x00, 0xde9a9270)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,bool,address)`.
+ mstore(0x00, 0x1078f68d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,bool,bool)`.
+ mstore(0x00, 0x50709698)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,bool,uint256)`.
+ mstore(0x00, 0x12f21602)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,bool,string)`.
+ mstore(0x00, 0x2555fa46)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,uint256,address)`.
+ mstore(0x00, 0x088ef9d2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,uint256,bool)`.
+ mstore(0x00, 0xe8defba9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,uint256,uint256)`.
+ mstore(0x00, 0x37103367)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,uint256,string)`.
+ mstore(0x00, 0xc3fc3970)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,string,address)`.
+ mstore(0x00, 0x9591b953)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,string,bool)`.
+ mstore(0x00, 0xdbb4c247)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,string,uint256)`.
+ mstore(0x00, 0x1093ee11)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(bool,string,string)`.
+ mstore(0x00, 0xb076847f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p1)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,address,address)`.
+ mstore(0x00, 0xbcfd9be0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,address,bool)`.
+ mstore(0x00, 0x9b6ec042)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,address,uint256)`.
+ mstore(0x00, 0x5a9b5ed5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,address,string)`.
+ mstore(0x00, 0x63cb41f9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,bool,address)`.
+ mstore(0x00, 0x35085f7b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,bool,bool)`.
+ mstore(0x00, 0x20718650)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,bool,uint256)`.
+ mstore(0x00, 0x20098014)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,bool,string)`.
+ mstore(0x00, 0x85775021)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,uint256,address)`.
+ mstore(0x00, 0x5c96b331)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,uint256,bool)`.
+ mstore(0x00, 0x4766da72)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,uint256,uint256)`.
+ mstore(0x00, 0xd1ed7a3c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,uint256,string)`.
+ mstore(0x00, 0x71d04af2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,string,address)`.
+ mstore(0x00, 0x7afac959)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,string,bool)`.
+ mstore(0x00, 0x4ceda75a)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,string,uint256)`.
+ mstore(0x00, 0x37aa7d4c)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(uint256,string,string)`.
+ mstore(0x00, 0xb115611f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p1)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,address,address)`.
+ mstore(0x00, 0xfcec75e0)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,address,bool)`.
+ mstore(0x00, 0xc91d5ed4)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,address,uint256)`.
+ mstore(0x00, 0x0d26b925)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,address,string)`.
+ mstore(0x00, 0xe0e9ad4f)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p0)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,bool,address)`.
+ mstore(0x00, 0x932bbb38)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,bool,bool)`.
+ mstore(0x00, 0x850b7ad6)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,bool,uint256)`.
+ mstore(0x00, 0xc95958d6)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,bool,string)`.
+ mstore(0x00, 0xe298f47d)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p0)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,uint256,address)`.
+ mstore(0x00, 0x1c7ec448)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,uint256,bool)`.
+ mstore(0x00, 0xca7733b1)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,uint256,uint256)`.
+ mstore(0x00, 0xca47c4eb)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,uint256,string)`.
+ mstore(0x00, 0x5970e089)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p0)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,string,address)`.
+ mstore(0x00, 0x95ed0195)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,string,bool)`.
+ mstore(0x00, 0xb0e0f9b5)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,string,uint256)`.
+ mstore(0x00, 0x5821efa1)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ // Selector of `log(string,string,string)`.
+ mstore(0x00, 0x2ced7cef)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, 0xe0)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ writeString(0x100, p2)
+ }
+ _sendLogPayload(0x1c, 0x124);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ }
+ }
+
+ function log(address p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,address,address)`.
+ mstore(0x00, 0x665bf134)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,address,bool)`.
+ mstore(0x00, 0x0e378994)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,address,uint256)`.
+ mstore(0x00, 0x94250d77)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,address,string)`.
+ mstore(0x00, 0xf808da20)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,bool,address)`.
+ mstore(0x00, 0x9f1bc36e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,bool,bool)`.
+ mstore(0x00, 0x2cd4134a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,bool,uint256)`.
+ mstore(0x00, 0x3971e78c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,bool,string)`.
+ mstore(0x00, 0xaa6540c8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,uint256,address)`.
+ mstore(0x00, 0x8da6def5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,uint256,bool)`.
+ mstore(0x00, 0x9b4254e2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,uint256,uint256)`.
+ mstore(0x00, 0xbe553481)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,uint256,string)`.
+ mstore(0x00, 0xfdb4f990)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,string,address)`.
+ mstore(0x00, 0x8f736d16)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,string,bool)`.
+ mstore(0x00, 0x6f1a594e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,string,uint256)`.
+ mstore(0x00, 0xef1cefe7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,address,string,string)`.
+ mstore(0x00, 0x21bdaf25)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,address,address)`.
+ mstore(0x00, 0x660375dd)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,address,bool)`.
+ mstore(0x00, 0xa6f50b0f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,address,uint256)`.
+ mstore(0x00, 0xa75c59de)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,address,string)`.
+ mstore(0x00, 0x2dd778e6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,bool,address)`.
+ mstore(0x00, 0xcf394485)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,bool,bool)`.
+ mstore(0x00, 0xcac43479)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,bool,uint256)`.
+ mstore(0x00, 0x8c4e5de6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,bool,string)`.
+ mstore(0x00, 0xdfc4a2e8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,uint256,address)`.
+ mstore(0x00, 0xccf790a1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,uint256,bool)`.
+ mstore(0x00, 0xc4643e20)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,uint256,uint256)`.
+ mstore(0x00, 0x386ff5f4)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,uint256,string)`.
+ mstore(0x00, 0x0aa6cfad)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,string,address)`.
+ mstore(0x00, 0x19fd4956)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,string,bool)`.
+ mstore(0x00, 0x50ad461d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,string,uint256)`.
+ mstore(0x00, 0x80e6a20b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,bool,string,string)`.
+ mstore(0x00, 0x475c5c33)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,address,address)`.
+ mstore(0x00, 0x478d1c62)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,address,bool)`.
+ mstore(0x00, 0xa1bcc9b3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,address,uint256)`.
+ mstore(0x00, 0x100f650e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,address,string)`.
+ mstore(0x00, 0x1da986ea)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,bool,address)`.
+ mstore(0x00, 0xa31bfdcc)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,bool,bool)`.
+ mstore(0x00, 0x3bf5e537)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,bool,uint256)`.
+ mstore(0x00, 0x22f6b999)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,bool,string)`.
+ mstore(0x00, 0xc5ad85f9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,uint256,address)`.
+ mstore(0x00, 0x20e3984d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,uint256,bool)`.
+ mstore(0x00, 0x66f1bc67)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,uint256,uint256)`.
+ mstore(0x00, 0x34f0e636)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,uint256,string)`.
+ mstore(0x00, 0x4a28c017)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,string,address)`.
+ mstore(0x00, 0x5c430d47)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,string,bool)`.
+ mstore(0x00, 0xcf18105c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,string,uint256)`.
+ mstore(0x00, 0xbf01f891)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,uint256,string,string)`.
+ mstore(0x00, 0x88a8c406)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,address,address)`.
+ mstore(0x00, 0x0d36fa20)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,address,bool)`.
+ mstore(0x00, 0x0df12b76)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,address,uint256)`.
+ mstore(0x00, 0x457fe3cf)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,address,string)`.
+ mstore(0x00, 0xf7e36245)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,bool,address)`.
+ mstore(0x00, 0x205871c2)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,bool,bool)`.
+ mstore(0x00, 0x5f1d5c9f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,bool,uint256)`.
+ mstore(0x00, 0x515e38b6)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,bool,string)`.
+ mstore(0x00, 0xbc0b61fe)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,uint256,address)`.
+ mstore(0x00, 0x63183678)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,uint256,bool)`.
+ mstore(0x00, 0x0ef7e050)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,uint256,uint256)`.
+ mstore(0x00, 0x1dc8e1b8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,uint256,string)`.
+ mstore(0x00, 0x448830a8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,string,address)`.
+ mstore(0x00, 0xa04e2f87)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,string,bool)`.
+ mstore(0x00, 0x35a5071f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,string,uint256)`.
+ mstore(0x00, 0x159f8927)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(address,string,string,string)`.
+ mstore(0x00, 0x5d02c50b)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,address,address)`.
+ mstore(0x00, 0x1d14d001)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,address,bool)`.
+ mstore(0x00, 0x46600be0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,address,uint256)`.
+ mstore(0x00, 0x0c66d1be)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,address,string)`.
+ mstore(0x00, 0xd812a167)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,bool,address)`.
+ mstore(0x00, 0x1c41a336)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,bool,bool)`.
+ mstore(0x00, 0x6a9c478b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,bool,uint256)`.
+ mstore(0x00, 0x07831502)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,bool,string)`.
+ mstore(0x00, 0x4a66cb34)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,uint256,address)`.
+ mstore(0x00, 0x136b05dd)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,uint256,bool)`.
+ mstore(0x00, 0xd6019f1c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,uint256,uint256)`.
+ mstore(0x00, 0x7bf181a1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,uint256,string)`.
+ mstore(0x00, 0x51f09ff8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,string,address)`.
+ mstore(0x00, 0x6f7c603e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,string,bool)`.
+ mstore(0x00, 0xe2bfd60b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,string,uint256)`.
+ mstore(0x00, 0xc21f64c7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,address,string,string)`.
+ mstore(0x00, 0xa73c1db6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,address,address)`.
+ mstore(0x00, 0xf4880ea4)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,address,bool)`.
+ mstore(0x00, 0xc0a302d8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,address,uint256)`.
+ mstore(0x00, 0x4c123d57)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,address,string)`.
+ mstore(0x00, 0xa0a47963)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,bool,address)`.
+ mstore(0x00, 0x8c329b1a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,bool,bool)`.
+ mstore(0x00, 0x3b2a5ce0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,bool,uint256)`.
+ mstore(0x00, 0x6d7045c1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,bool,string)`.
+ mstore(0x00, 0x2ae408d4)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,uint256,address)`.
+ mstore(0x00, 0x54a7a9a0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,uint256,bool)`.
+ mstore(0x00, 0x619e4d0e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,uint256,uint256)`.
+ mstore(0x00, 0x0bb00eab)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,uint256,string)`.
+ mstore(0x00, 0x7dd4d0e0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,string,address)`.
+ mstore(0x00, 0xf9ad2b89)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,string,bool)`.
+ mstore(0x00, 0xb857163a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,string,uint256)`.
+ mstore(0x00, 0xe3a9ca2f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,bool,string,string)`.
+ mstore(0x00, 0x6d1e8751)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,address,address)`.
+ mstore(0x00, 0x26f560a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,address,bool)`.
+ mstore(0x00, 0xb4c314ff)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,address,uint256)`.
+ mstore(0x00, 0x1537dc87)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,address,string)`.
+ mstore(0x00, 0x1bb3b09a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,bool,address)`.
+ mstore(0x00, 0x9acd3616)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,bool,bool)`.
+ mstore(0x00, 0xceb5f4d7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,bool,uint256)`.
+ mstore(0x00, 0x7f9bbca2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,bool,string)`.
+ mstore(0x00, 0x9143dbb1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,uint256,address)`.
+ mstore(0x00, 0x00dd87b9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,uint256,bool)`.
+ mstore(0x00, 0xbe984353)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,uint256,uint256)`.
+ mstore(0x00, 0x374bb4b2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,uint256,string)`.
+ mstore(0x00, 0x8e69fb5d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,string,address)`.
+ mstore(0x00, 0xfedd1fff)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,string,bool)`.
+ mstore(0x00, 0xe5e70b2b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,string,uint256)`.
+ mstore(0x00, 0x6a1199e2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,uint256,string,string)`.
+ mstore(0x00, 0xf5bc2249)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,address,address)`.
+ mstore(0x00, 0x2b2b18dc)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,address,bool)`.
+ mstore(0x00, 0x6dd434ca)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,address,uint256)`.
+ mstore(0x00, 0xa5cada94)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,address,string)`.
+ mstore(0x00, 0x12d6c788)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,bool,address)`.
+ mstore(0x00, 0x538e06ab)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,bool,bool)`.
+ mstore(0x00, 0xdc5e935b)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,bool,uint256)`.
+ mstore(0x00, 0x1606a393)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,bool,string)`.
+ mstore(0x00, 0x483d0416)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,uint256,address)`.
+ mstore(0x00, 0x1596a1ce)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,uint256,bool)`.
+ mstore(0x00, 0x6b0e5d53)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,uint256,uint256)`.
+ mstore(0x00, 0x28863fcb)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,uint256,string)`.
+ mstore(0x00, 0x1ad96de6)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,string,address)`.
+ mstore(0x00, 0x97d394d8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,string,bool)`.
+ mstore(0x00, 0x1e4b87e5)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,string,uint256)`.
+ mstore(0x00, 0x7be0c3eb)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(bool,string,string,string)`.
+ mstore(0x00, 0x1762e32a)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,address,address)`.
+ mstore(0x00, 0x2488b414)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,address,bool)`.
+ mstore(0x00, 0x091ffaf5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,address,uint256)`.
+ mstore(0x00, 0x736efbb6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,address,string)`.
+ mstore(0x00, 0x031c6f73)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,bool,address)`.
+ mstore(0x00, 0xef72c513)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,bool,bool)`.
+ mstore(0x00, 0xe351140f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,bool,uint256)`.
+ mstore(0x00, 0x5abd992a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,bool,string)`.
+ mstore(0x00, 0x90fb06aa)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,uint256,address)`.
+ mstore(0x00, 0x15c127b5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,uint256,bool)`.
+ mstore(0x00, 0x5f743a7c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,uint256,uint256)`.
+ mstore(0x00, 0x0c9cd9c1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,uint256,string)`.
+ mstore(0x00, 0xddb06521)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,string,address)`.
+ mstore(0x00, 0x9cba8fff)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,string,bool)`.
+ mstore(0x00, 0xcc32ab07)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,string,uint256)`.
+ mstore(0x00, 0x46826b5d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,address,string,string)`.
+ mstore(0x00, 0x3e128ca3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,address,address)`.
+ mstore(0x00, 0xa1ef4cbb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,address,bool)`.
+ mstore(0x00, 0x454d54a5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,address,uint256)`.
+ mstore(0x00, 0x078287f5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,address,string)`.
+ mstore(0x00, 0xade052c7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,bool,address)`.
+ mstore(0x00, 0x69640b59)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,bool,bool)`.
+ mstore(0x00, 0xb6f577a1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,bool,uint256)`.
+ mstore(0x00, 0x7464ce23)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,bool,string)`.
+ mstore(0x00, 0xdddb9561)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,uint256,address)`.
+ mstore(0x00, 0x88cb6041)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,uint256,bool)`.
+ mstore(0x00, 0x91a02e2a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,uint256,uint256)`.
+ mstore(0x00, 0xc6acc7a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,uint256,string)`.
+ mstore(0x00, 0xde03e774)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,string,address)`.
+ mstore(0x00, 0xef529018)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,string,bool)`.
+ mstore(0x00, 0xeb928d7f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,string,uint256)`.
+ mstore(0x00, 0x2c1d0746)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,bool,string,string)`.
+ mstore(0x00, 0x68c8b8bd)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,address,address)`.
+ mstore(0x00, 0x56a5d1b1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,address,bool)`.
+ mstore(0x00, 0x15cac476)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,address,uint256)`.
+ mstore(0x00, 0x88f6e4b2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,address,string)`.
+ mstore(0x00, 0x6cde40b8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,bool,address)`.
+ mstore(0x00, 0x9a816a83)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,bool,bool)`.
+ mstore(0x00, 0xab085ae6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,bool,uint256)`.
+ mstore(0x00, 0xeb7f6fd2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,bool,string)`.
+ mstore(0x00, 0xa5b4fc99)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,uint256,address)`.
+ mstore(0x00, 0xfa8185af)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,uint256,bool)`.
+ mstore(0x00, 0xc598d185)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,uint256,uint256)`.
+ mstore(0x00, 0x193fb800)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,uint256,string)`.
+ mstore(0x00, 0x59cfcbe3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,string,address)`.
+ mstore(0x00, 0x42d21db7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,string,bool)`.
+ mstore(0x00, 0x7af6ab25)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,string,uint256)`.
+ mstore(0x00, 0x5da297eb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,uint256,string,string)`.
+ mstore(0x00, 0x27d8afd2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,address,address)`.
+ mstore(0x00, 0x6168ed61)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,address,bool)`.
+ mstore(0x00, 0x90c30a56)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,address,uint256)`.
+ mstore(0x00, 0xe8d3018d)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,address,string)`.
+ mstore(0x00, 0x9c3adfa1)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,bool,address)`.
+ mstore(0x00, 0xae2ec581)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,bool,bool)`.
+ mstore(0x00, 0xba535d9c)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,bool,uint256)`.
+ mstore(0x00, 0xcf009880)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,bool,string)`.
+ mstore(0x00, 0xd2d423cd)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,uint256,address)`.
+ mstore(0x00, 0x3b2279b4)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,uint256,bool)`.
+ mstore(0x00, 0x691a8f74)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,uint256,uint256)`.
+ mstore(0x00, 0x82c25b74)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,uint256,string)`.
+ mstore(0x00, 0xb7b914ca)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,string,address)`.
+ mstore(0x00, 0xd583c602)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,string,bool)`.
+ mstore(0x00, 0xb3a6b6bd)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,string,uint256)`.
+ mstore(0x00, 0xb028c9bd)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(uint256,string,string,string)`.
+ mstore(0x00, 0x21ad0683)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,address,address)`.
+ mstore(0x00, 0xed8f28f6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,address,bool)`.
+ mstore(0x00, 0xb59dbd60)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,address,uint256)`.
+ mstore(0x00, 0x8ef3f399)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,address,string)`.
+ mstore(0x00, 0x800a1c67)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,bool,address)`.
+ mstore(0x00, 0x223603bd)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,bool,bool)`.
+ mstore(0x00, 0x79884c2b)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,bool,uint256)`.
+ mstore(0x00, 0x3e9f866a)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,bool,string)`.
+ mstore(0x00, 0x0454c079)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,uint256,address)`.
+ mstore(0x00, 0x63fb8bc5)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,uint256,bool)`.
+ mstore(0x00, 0xfc4845f0)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,uint256,uint256)`.
+ mstore(0x00, 0xf8f51b1e)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,uint256,string)`.
+ mstore(0x00, 0x5a477632)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,string,address)`.
+ mstore(0x00, 0xaabc9a31)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,string,bool)`.
+ mstore(0x00, 0x5f15d28c)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,string,uint256)`.
+ mstore(0x00, 0x91d1112e)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,address,string,string)`.
+ mstore(0x00, 0x245986f2)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,address,address)`.
+ mstore(0x00, 0x33e9dd1d)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,address,bool)`.
+ mstore(0x00, 0x958c28c6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,address,uint256)`.
+ mstore(0x00, 0x5d08bb05)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,address,string)`.
+ mstore(0x00, 0x2d8e33a4)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,bool,address)`.
+ mstore(0x00, 0x7190a529)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,bool,bool)`.
+ mstore(0x00, 0x895af8c5)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,bool,uint256)`.
+ mstore(0x00, 0x8e3f78a9)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,bool,string)`.
+ mstore(0x00, 0x9d22d5dd)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,uint256,address)`.
+ mstore(0x00, 0x935e09bf)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,uint256,bool)`.
+ mstore(0x00, 0x8af7cf8a)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,uint256,uint256)`.
+ mstore(0x00, 0x64b5bb67)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,uint256,string)`.
+ mstore(0x00, 0x742d6ee7)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,string,address)`.
+ mstore(0x00, 0xe0625b29)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,string,bool)`.
+ mstore(0x00, 0x3f8a701d)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,string,uint256)`.
+ mstore(0x00, 0x24f91465)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,bool,string,string)`.
+ mstore(0x00, 0xa826caeb)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,address,address)`.
+ mstore(0x00, 0x5ea2b7ae)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,address,bool)`.
+ mstore(0x00, 0x82112a42)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,address,uint256)`.
+ mstore(0x00, 0x4f04fdc6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,address,string)`.
+ mstore(0x00, 0x9ffb2f93)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,bool,address)`.
+ mstore(0x00, 0xe0e95b98)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,bool,bool)`.
+ mstore(0x00, 0x354c36d6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,bool,uint256)`.
+ mstore(0x00, 0xe41b6f6f)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,bool,string)`.
+ mstore(0x00, 0xabf73a98)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,uint256,address)`.
+ mstore(0x00, 0xe21de278)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,uint256,bool)`.
+ mstore(0x00, 0x7626db92)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,uint256,uint256)`.
+ mstore(0x00, 0xa7a87853)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,uint256,string)`.
+ mstore(0x00, 0x854b3496)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,string,address)`.
+ mstore(0x00, 0x7c4632a4)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,string,bool)`.
+ mstore(0x00, 0x7d24491d)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,string,uint256)`.
+ mstore(0x00, 0xc67ea9d1)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,uint256,string,string)`.
+ mstore(0x00, 0x5ab84e1f)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,address,address)`.
+ mstore(0x00, 0x439c7bef)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,address,bool)`.
+ mstore(0x00, 0x5ccd4e37)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,address,uint256)`.
+ mstore(0x00, 0x7cc3c607)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,address,string)`.
+ mstore(0x00, 0xeb1bff80)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,bool,address)`.
+ mstore(0x00, 0xc371c7db)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,bool,bool)`.
+ mstore(0x00, 0x40785869)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,bool,uint256)`.
+ mstore(0x00, 0xd6aefad2)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,bool,string)`.
+ mstore(0x00, 0x5e84b0ea)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,uint256,address)`.
+ mstore(0x00, 0x1023f7b2)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,uint256,bool)`.
+ mstore(0x00, 0xc3a8a654)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,uint256,uint256)`.
+ mstore(0x00, 0xf45d7d2c)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,uint256,string)`.
+ mstore(0x00, 0x5d1a971a)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,string,address)`.
+ mstore(0x00, 0x6d572f44)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,string,bool)`.
+ mstore(0x00, 0x2c1754ed)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,string,uint256)`.
+ mstore(0x00, 0x8eafb02b)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ bytes32 m11;
+ bytes32 m12;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ m11 := mload(0x160)
+ m12 := mload(0x180)
+ // Selector of `log(string,string,string,string)`.
+ mstore(0x00, 0xde68f20a)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, 0x140)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ writeString(0x160, p3)
+ }
+ _sendLogPayload(0x1c, 0x184);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ mstore(0x160, m11)
+ mstore(0x180, m12)
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/CommonBase.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/CommonBase.t.sol
new file mode 100644
index 000000000..4a6eb34fd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/CommonBase.t.sol
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {CommonBase} from "../src/Base.sol";
+import {StdConstants} from "../src/StdConstants.sol";
+import {Test} from "../src/Test.sol";
+
+contract CommonBaseTest is Test {
+ function testVmAddressValue() public pure {
+ assertEq(VM_ADDRESS, address(StdConstants.VM));
+ }
+
+ function testConsoleValue() public pure {
+ assertEq(CONSOLE, StdConstants.CONSOLE);
+ }
+
+ function testCreate2FactoryValue() public pure {
+ assertEq(CREATE2_FACTORY, StdConstants.CREATE2_FACTORY);
+ }
+
+ function testDefaultSenderValue() public pure {
+ assertEq(DEFAULT_SENDER, StdConstants.DEFAULT_SENDER);
+ }
+
+ function testDefaultTestContractValue() public pure {
+ assertEq(DEFAULT_TEST_CONTRACT, StdConstants.DEFAULT_TEST_CONTRACT);
+ }
+
+ function testMulticall3AddressValue() public pure {
+ assertEq(MULTICALL3_ADDRESS, address(StdConstants.MULTICALL3_ADDRESS));
+ }
+
+ function testSecp256k1OrderValue() public pure {
+ assertEq(SECP256K1_ORDER, StdConstants.SECP256K1_ORDER);
+ }
+
+ function testUint256MaxValue() public pure {
+ assertEq(UINT256_MAX, type(uint256).max);
+ }
+
+ function testVmValue() public pure {
+ assertEq(address(vm), address(StdConstants.VM));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/Config.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/Config.t.sol
new file mode 100644
index 000000000..8e2342cad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/Config.t.sol
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+import {Test} from "../src/Test.sol";
+import {Config} from "../src/Config.sol";
+import {StdConfig} from "../src/StdConfig.sol";
+
+contract ConfigTest is Test, Config {
+ function setUp() public {
+ vm.setEnv("MAINNET_RPC", "https://eth.llamarpc.com");
+ vm.setEnv("WETH_MAINNET", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2");
+ vm.setEnv("OPTIMISM_RPC", "https://mainnet.optimism.io");
+ vm.setEnv("WETH_OPTIMISM", "0x4200000000000000000000000000000000000006");
+ }
+
+ function test_loadConfig() public {
+ // Deploy the config contract with the test fixture.
+ _loadConfig("./test/fixtures/config.toml", false);
+
+ // -- MAINNET --------------------------------------------------------------
+
+ // Read and assert RPC URL for Mainnet (chain ID 1)
+ assertEq(config.getRpcUrl(1), "https://eth.llamarpc.com");
+
+ // Read and assert boolean values
+ assertTrue(config.get(1, "is_live").toBool());
+ bool[] memory bool_array = config.get(1, "bool_array").toBoolArray();
+ assertTrue(bool_array[0]);
+ assertFalse(bool_array[1]);
+
+ // Read and assert address values
+ assertEq(config.get(1, "weth").toAddress(), 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
+ address[] memory address_array = config.get(1, "deps").toAddressArray();
+ assertEq(address_array[0], 0x0000000000000000000000000000000000000000);
+ assertEq(address_array[1], 0x1111111111111111111111111111111111111111);
+
+ // Read and assert bytes32 values
+ assertEq(config.get(1, "word").toBytes32(), bytes32(uint256(1234)));
+ bytes32[] memory bytes32_array = config.get(1, "word_array").toBytes32Array();
+ assertEq(bytes32_array[0], bytes32(uint256(5678)));
+ assertEq(bytes32_array[1], bytes32(uint256(9999)));
+
+ // Read and assert uint values
+ assertEq(config.get(1, "number").toUint256(), 1234);
+ uint256[] memory uint_array = config.get(1, "number_array").toUint256Array();
+ assertEq(uint_array[0], 5678);
+ assertEq(uint_array[1], 9999);
+
+ // Read and assert int values
+ assertEq(config.get(1, "signed_number").toInt256(), -1234);
+ int256[] memory int_array = config.get(1, "signed_number_array").toInt256Array();
+ assertEq(int_array[0], -5678);
+ assertEq(int_array[1], 9999);
+
+ // Read and assert bytes values
+ assertEq(config.get(1, "b").toBytes(), hex"abcd");
+ bytes[] memory bytes_array = config.get(1, "b_array").toBytesArray();
+ assertEq(bytes_array[0], hex"dead");
+ assertEq(bytes_array[1], hex"beef");
+
+ // Read and assert string values
+ assertEq(config.get(1, "str").toString(), "foo");
+ string[] memory string_array = config.get(1, "str_array").toStringArray();
+ assertEq(string_array[0], "bar");
+ assertEq(string_array[1], "baz");
+
+ // -- OPTIMISM ------------------------------------------------------------
+
+ // Read and assert RPC URL for Optimism (chain ID 10)
+ assertEq(config.getRpcUrl(10), "https://mainnet.optimism.io");
+
+ // Read and assert boolean values
+ assertFalse(config.get(10, "is_live").toBool());
+ bool_array = config.get(10, "bool_array").toBoolArray();
+ assertFalse(bool_array[0]);
+ assertTrue(bool_array[1]);
+
+ // Read and assert address values
+ assertEq(config.get(10, "weth").toAddress(), 0x4200000000000000000000000000000000000006);
+ address_array = config.get(10, "deps").toAddressArray();
+ assertEq(address_array[0], 0x2222222222222222222222222222222222222222);
+ assertEq(address_array[1], 0x3333333333333333333333333333333333333333);
+
+ // Read and assert bytes32 values
+ assertEq(config.get(10, "word").toBytes32(), bytes32(uint256(9999)));
+ bytes32_array = config.get(10, "word_array").toBytes32Array();
+ assertEq(bytes32_array[0], bytes32(uint256(1234)));
+ assertEq(bytes32_array[1], bytes32(uint256(5678)));
+
+ // Read and assert uint values
+ assertEq(config.get(10, "number").toUint256(), 9999);
+ uint_array = config.get(10, "number_array").toUint256Array();
+ assertEq(uint_array[0], 1234);
+ assertEq(uint_array[1], 5678);
+
+ // Read and assert int values
+ assertEq(config.get(10, "signed_number").toInt256(), 9999);
+ int_array = config.get(10, "signed_number_array").toInt256Array();
+ assertEq(int_array[0], -1234);
+ assertEq(int_array[1], -5678);
+
+ // Read and assert bytes values
+ assertEq(config.get(10, "b").toBytes(), hex"dcba");
+ bytes_array = config.get(10, "b_array").toBytesArray();
+ assertEq(bytes_array[0], hex"c0ffee");
+ assertEq(bytes_array[1], hex"babe");
+
+ // Read and assert string values
+ assertEq(config.get(10, "str").toString(), "alice");
+ string_array = config.get(10, "str_array").toStringArray();
+ assertEq(string_array[0], "bob");
+ assertEq(string_array[1], "charlie");
+ }
+
+ function test_loadConfigAndForks() public {
+ _loadConfigAndForks("./test/fixtures/config.toml", false);
+
+ // assert that the map of chain id and fork ids is created and that the chain ids actually match
+ assertEq(forkOf[1], 0);
+ vm.selectFork(forkOf[1]);
+ assertEq(vm.getChainId(), 1);
+
+ assertEq(forkOf[10], 1);
+ vm.selectFork(forkOf[10]);
+ assertEq(vm.getChainId(), 10);
+ }
+
+ function test_writeConfig() public {
+ // Create a temporary copy of the config file to avoid modifying the original.
+ string memory originalConfig = "./test/fixtures/config.toml";
+ string memory testConfig = "./test/fixtures/config.t.toml";
+ vm.copyFile(originalConfig, testConfig);
+
+ // Deploy the config contract with the temporary fixture.
+ _loadConfig(testConfig, false);
+
+ // Enable writing to file bypassing the context check.
+ vm.store(address(config), bytes32(uint256(5)), bytes32(uint256(1)));
+
+ {
+ // Update a single boolean value and verify the change.
+ config.set(1, "is_live", false);
+
+ assertFalse(config.get(1, "is_live").toBool());
+
+ string memory content = vm.readFile(testConfig);
+ assertFalse(vm.parseTomlBool(content, "$.mainnet.bool.is_live"));
+
+ // Update a single address value and verify the change.
+ address new_addr = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF;
+ config.set(1, "weth", new_addr);
+
+ assertEq(config.get(1, "weth").toAddress(), new_addr);
+
+ content = vm.readFile(testConfig);
+ assertEq(vm.parseTomlAddress(content, "$.mainnet.address.weth"), new_addr);
+
+ // Update a uint array and verify the change.
+ uint256[] memory new_numbers = new uint256[](3);
+ new_numbers[0] = 1;
+ new_numbers[1] = 2;
+ new_numbers[2] = 3;
+ config.set(10, "number_array", new_numbers);
+
+ uint256[] memory updated_numbers_mem = config.get(10, "number_array").toUint256Array();
+ assertEq(updated_numbers_mem.length, 3);
+ assertEq(updated_numbers_mem[0], 1);
+ assertEq(updated_numbers_mem[1], 2);
+ assertEq(updated_numbers_mem[2], 3);
+
+ content = vm.readFile(testConfig);
+ uint256[] memory updated_numbers_disk = vm.parseTomlUintArray(content, "$.optimism.uint.number_array");
+ assertEq(updated_numbers_disk.length, 3);
+ assertEq(updated_numbers_disk[0], 1);
+ assertEq(updated_numbers_disk[1], 2);
+ assertEq(updated_numbers_disk[2], 3);
+
+ // Update a string array and verify the change.
+ string[] memory new_strings = new string[](2);
+ new_strings[0] = "hello";
+ new_strings[1] = "world";
+ config.set(1, "str_array", new_strings);
+
+ string[] memory updated_strings_mem = config.get(1, "str_array").toStringArray();
+ assertEq(updated_strings_mem.length, 2);
+ assertEq(updated_strings_mem[0], "hello");
+ assertEq(updated_strings_mem[1], "world");
+
+ content = vm.readFile(testConfig);
+ string[] memory updated_strings_disk = vm.parseTomlStringArray(content, "$.mainnet.string.str_array");
+ assertEq(updated_strings_disk.length, 2);
+ assertEq(updated_strings_disk[0], "hello");
+ assertEq(updated_strings_disk[1], "world");
+
+ // Create a new uint variable and verify the change.
+ config.set(1, "new_uint", uint256(42));
+
+ assertEq(config.get(1, "new_uint").toUint256(), 42);
+
+ content = vm.readFile(testConfig);
+ assertEq(vm.parseTomlUint(content, "$.mainnet.uint.new_uint"), 42);
+
+ // Create a new int variable and verify the change.
+ config.set(1, "new_int", int256(-42));
+
+ assertEq(config.get(1, "new_int").toInt256(), -42);
+
+ content = vm.readFile(testConfig);
+ assertEq(vm.parseTomlInt(content, "$.mainnet.int.new_int"), -42);
+
+ // Create a new int array and verify the change.
+ int256[] memory new_ints = new int256[](2);
+ new_ints[0] = -100;
+ new_ints[1] = 200;
+ config.set(10, "new_ints", new_ints);
+
+ int256[] memory updated_ints_mem = config.get(10, "new_ints").toInt256Array();
+ assertEq(updated_ints_mem.length, 2);
+ assertEq(updated_ints_mem[0], -100);
+ assertEq(updated_ints_mem[1], 200);
+
+ content = vm.readFile(testConfig);
+ int256[] memory updated_ints_disk = vm.parseTomlIntArray(content, "$.optimism.int.new_ints");
+ assertEq(updated_ints_disk.length, 2);
+ assertEq(updated_ints_disk[0], -100);
+ assertEq(updated_ints_disk[1], 200);
+
+ // Create a new bytes32 array and verify the change.
+ bytes32[] memory new_words = new bytes32[](2);
+ new_words[0] = bytes32(uint256(0xDEAD));
+ new_words[1] = bytes32(uint256(0xBEEF));
+ config.set(10, "new_words", new_words);
+
+ bytes32[] memory updated_words_mem = config.get(10, "new_words").toBytes32Array();
+ assertEq(updated_words_mem.length, 2);
+ assertEq(updated_words_mem[0], new_words[0]);
+ assertEq(updated_words_mem[1], new_words[1]);
+
+ content = vm.readFile(testConfig);
+ bytes32[] memory updated_words_disk = vm.parseTomlBytes32Array(content, "$.optimism.bytes32.new_words");
+ assertEq(updated_words_disk.length, 2);
+ assertEq(vm.toString(updated_words_disk[0]), vm.toString(new_words[0]));
+ assertEq(vm.toString(updated_words_disk[1]), vm.toString(new_words[1]));
+ }
+
+ // Clean up the temporary file.
+ vm.removeFile(testConfig);
+ }
+
+ function test_writeUpdatesBackToFile() public {
+ // Create a temporary copy of the config file to avoid modifying the original.
+ string memory originalConfig = "./test/fixtures/config.toml";
+ string memory testConfig = "./test/fixtures/write_config.t.toml";
+ vm.copyFile(originalConfig, testConfig);
+
+ // Deploy the config contract with `writeToFile = false` (disabled).
+ _loadConfig(testConfig, false);
+
+ // Update a single boolean value and verify the file is NOT changed.
+ config.set(1, "is_live", false);
+ string memory content = vm.readFile(testConfig);
+ assertTrue(vm.parseTomlBool(content, "$.mainnet.bool.is_live"), "File should not be updated yet");
+
+ // Enable writing to file bypassing the context check.
+ vm.store(address(config), bytes32(uint256(5)), bytes32(uint256(1)));
+
+ // Update the value again and verify the file IS changed.
+ config.set(1, "is_live", false);
+ content = vm.readFile(testConfig);
+ assertFalse(vm.parseTomlBool(content, "$.mainnet.bool.is_live"), "File should be updated now");
+
+ // Disable writing to file.
+ config.writeUpdatesBackToFile(false);
+
+ // Update the value again and verify the file is NOT changed.
+ config.set(1, "is_live", true);
+ content = vm.readFile(testConfig);
+ assertFalse(vm.parseTomlBool(content, "$.mainnet.bool.is_live"), "File should not be updated again");
+
+ // Clean up the temporary file.
+ vm.removeFile(testConfig);
+ }
+
+ function testRevert_WriteToFileInForbiddenCtxt() public {
+ // Cannot initialize enabling writing to file unless we are in SCRIPT mode.
+ vm.expectRevert(StdConfig.WriteToFileInForbiddenCtxt.selector);
+ _loadConfig("./test/fixtures/config.toml", true);
+
+ // Initialize with `writeToFile = false`.
+ _loadConfig("./test/fixtures/config.toml", false);
+
+ // Cannot enable writing to file unless we are in SCRIPT mode.
+ vm.expectRevert(StdConfig.WriteToFileInForbiddenCtxt.selector);
+ config.writeUpdatesBackToFile(true);
+ }
+
+ function testRevert_InvalidChainKey() public {
+ // Create a fixture with an invalid chain key
+ string memory invalidChainConfig = "./test/fixtures/config_invalid_chain.toml";
+ vm.writeFile(
+ invalidChainConfig,
+ string.concat(
+ "[mainnet]\n",
+ "endpoint_url = \"https://eth.llamarpc.com\"\n",
+ "\n",
+ "[mainnet.uint]\n",
+ "valid_number = 123\n",
+ "\n",
+ "# Invalid chain key (not a number and not a valid alias)\n",
+ "[invalid_chain]\n",
+ "endpoint_url = \"https://invalid.com\"\n",
+ "\n",
+ "[invalid_chain_9999.uint]\n",
+ "some_value = 456\n"
+ )
+ );
+
+ vm.expectRevert(abi.encodeWithSelector(StdConfig.InvalidChainKey.selector, "invalid_chain"));
+ new StdConfig(invalidChainConfig, false);
+ vm.removeFile(invalidChainConfig);
+ }
+
+ function testRevert_ChainNotInitialized() public {
+ _loadConfig("./test/fixtures/config.toml", false);
+
+ // Enable writing to file bypassing the context check.
+ vm.store(address(config), bytes32(uint256(5)), bytes32(uint256(1)));
+
+ // Try to write a value for a non-existent chain ID
+ vm.expectRevert(abi.encodeWithSelector(StdConfig.ChainNotInitialized.selector, uint256(999999)));
+ config.set(999999, "some_key", uint256(123));
+ }
+
+ function testRevert_UnableToParseVariable() public {
+ // Create a temporary fixture with an unparsable variable
+ string memory badParseConfig = "./test/fixtures/config_bad_parse.toml";
+ vm.writeFile(
+ badParseConfig,
+ string.concat(
+ "[mainnet]\n",
+ "endpoint_url = \"https://eth.llamarpc.com\"\n",
+ "\n",
+ "[mainnet.uint]\n",
+ "bad_value = \"not_a_number\"\n"
+ )
+ );
+
+ vm.expectRevert(abi.encodeWithSelector(StdConfig.UnableToParseVariable.selector, "bad_value"));
+ new StdConfig(badParseConfig, false);
+ vm.removeFile(badParseConfig);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/LibVariable.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/LibVariable.t.sol
new file mode 100644
index 000000000..2fc00a91a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/LibVariable.t.sol
@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+import {Test} from "../src/Test.sol";
+import {Variable, Type, TypeKind, LibVariable} from "../src/LibVariable.sol";
+
+contract LibVariableTest is Test {
+ using LibVariable for Type;
+ using LibVariable for TypeKind;
+
+ LibVariableHelper internal helper;
+
+ bytes internal expectedErr;
+ Variable internal uninitVar;
+ Variable internal boolVar;
+ Variable internal addressVar;
+ Variable internal bytes32Var;
+ Variable internal uintVar;
+ Variable internal intVar;
+ Variable internal stringVar;
+ Variable internal bytesVar;
+ Variable internal boolArrayVar;
+ Variable internal addressArrayVar;
+ Variable internal bytes32ArrayVar;
+ Variable internal uintArrayVar;
+ Variable internal intArrayVar;
+ Variable internal stringArrayVar;
+ Variable internal bytesArrayVar;
+
+ function setUp() public {
+ helper = new LibVariableHelper();
+
+ // UNINITIALIZED
+ uninitVar = Variable(Type(TypeKind.None, false), "");
+
+ // SINGLE VALUES
+ boolVar = Variable(Type(TypeKind.Bool, false), abi.encode(true));
+ addressVar = Variable(Type(TypeKind.Address, false), abi.encode(address(0xdeadbeef)));
+ bytes32Var = Variable(Type(TypeKind.Bytes32, false), abi.encode(bytes32(uint256(42))));
+ uintVar = Variable(Type(TypeKind.Uint256, false), abi.encode(uint256(123)));
+ intVar = Variable(Type(TypeKind.Int256, false), abi.encode(int256(-123)));
+ stringVar = Variable(Type(TypeKind.String, false), abi.encode("hello world"));
+ bytesVar = Variable(Type(TypeKind.Bytes, false), abi.encode(hex"c0ffee"));
+
+ // ARRAY VALUES
+ bool[] memory bools = new bool[](2);
+ bools[0] = true;
+ bools[1] = false;
+ boolArrayVar = Variable(Type(TypeKind.Bool, true), abi.encode(bools));
+
+ address[] memory addrs = new address[](2);
+ addrs[0] = address(0x1);
+ addrs[1] = address(0x2);
+ addressArrayVar = Variable(Type(TypeKind.Address, true), abi.encode(addrs));
+
+ bytes32[] memory b32s = new bytes32[](2);
+ b32s[0] = bytes32(uint256(1));
+ b32s[1] = bytes32(uint256(2));
+ bytes32ArrayVar = Variable(Type(TypeKind.Bytes32, true), abi.encode(b32s));
+
+ uint256[] memory uints = new uint256[](2);
+ uints[0] = 1;
+ uints[1] = 2;
+ uintArrayVar = Variable(Type(TypeKind.Uint256, true), abi.encode(uints));
+
+ int256[] memory ints = new int256[](2);
+ ints[0] = -1;
+ ints[1] = 2;
+ intArrayVar = Variable(Type(TypeKind.Int256, true), abi.encode(ints));
+
+ string[] memory strings = new string[](2);
+ strings[0] = "one";
+ strings[1] = "two";
+ stringArrayVar = Variable(Type(TypeKind.String, true), abi.encode(strings));
+
+ bytes[] memory b = new bytes[](2);
+ b[0] = hex"01";
+ b[1] = hex"02";
+ bytesArrayVar = Variable(Type(TypeKind.Bytes, true), abi.encode(b));
+ }
+
+ // -- SUCCESS CASES --------------------------------------------------------
+
+ function test_TypeHelpers() public view {
+ // TypeKind.toString()
+ assertEq(TypeKind.None.toString(), "none");
+ assertEq(TypeKind.Bool.toString(), "bool");
+ assertEq(TypeKind.Address.toString(), "address");
+ assertEq(TypeKind.Bytes32.toString(), "bytes32");
+ assertEq(TypeKind.Uint256.toString(), "uint256");
+ assertEq(TypeKind.Int256.toString(), "int256");
+ assertEq(TypeKind.String.toString(), "string");
+ assertEq(TypeKind.Bytes.toString(), "bytes");
+
+ // TypeKind.toTomlKey()
+ assertEq(TypeKind.Uint256.toTomlKey(), "uint");
+ assertEq(TypeKind.Int256.toTomlKey(), "int");
+ assertEq(TypeKind.Bytes32.toTomlKey(), "bytes32");
+
+ // Type.toString()
+ assertEq(boolVar.ty.toString(), "bool");
+ assertEq(boolArrayVar.ty.toString(), "bool[]");
+ assertEq(uintVar.ty.toString(), "uint256");
+ assertEq(uintArrayVar.ty.toString(), "uint256[]");
+ assertEq(uninitVar.ty.toString(), "none");
+
+ // Type.isEqual()
+ assertTrue(boolVar.ty.isEqual(Type(TypeKind.Bool, false)));
+ assertFalse(boolVar.ty.isEqual(Type(TypeKind.Bool, true)));
+ assertFalse(boolVar.ty.isEqual(Type(TypeKind.Address, false)));
+
+ // Type.assertEq()
+ boolVar.ty.assertEq(Type(TypeKind.Bool, false));
+ uintArrayVar.ty.assertEq(Type(TypeKind.Uint256, true));
+ }
+
+ function test_Coercion() public view {
+ // Single values
+ assertTrue(helper.toBool(boolVar));
+ assertEq(helper.toAddress(addressVar), address(0xdeadbeef));
+ assertEq(helper.toBytes32(bytes32Var), bytes32(uint256(42)));
+ assertEq(helper.toUint256(uintVar), 123);
+ assertEq(helper.toInt256(intVar), -123);
+ assertEq(helper.toString(stringVar), "hello world");
+ assertEq(helper.toBytes(bytesVar), hex"c0ffee");
+
+ // Bool array
+ bool[] memory bools = helper.toBoolArray(boolArrayVar);
+ assertEq(bools.length, 2);
+ assertTrue(bools[0]);
+ assertFalse(bools[1]);
+
+ // Address array
+ address[] memory addrs = helper.toAddressArray(addressArrayVar);
+ assertEq(addrs.length, 2);
+ assertEq(addrs[0], address(0x1));
+ assertEq(addrs[1], address(0x2));
+
+ // String array
+ string[] memory strings = helper.toStringArray(stringArrayVar);
+ assertEq(strings.length, 2);
+ assertEq(strings[0], "one");
+ assertEq(strings[1], "two");
+ }
+
+ function test_Downcasting() public view {
+ // Uint downcasting
+ Variable memory v_uint_small = Variable(Type(TypeKind.Uint256, false), abi.encode(uint256(100)));
+ assertEq(helper.toUint128(v_uint_small), 100);
+ assertEq(helper.toUint64(v_uint_small), 100);
+ assertEq(helper.toUint32(v_uint_small), 100);
+ assertEq(helper.toUint16(v_uint_small), 100);
+ assertEq(helper.toUint8(v_uint_small), 100);
+
+ // Uint array downcasting
+ uint256[] memory small_uints = new uint256[](2);
+ small_uints[0] = 10;
+ small_uints[1] = 20;
+ Variable memory v_uint_array_small = Variable(Type(TypeKind.Uint256, true), abi.encode(small_uints));
+ uint8[] memory u8_array = helper.toUint8Array(v_uint_array_small);
+ assertEq(u8_array[0], 10);
+ assertEq(u8_array[1], 20);
+
+ // Int downcasting
+ Variable memory v_int_small_pos = Variable(Type(TypeKind.Int256, false), abi.encode(int256(100)));
+ Variable memory v_int_small_neg = Variable(Type(TypeKind.Int256, false), abi.encode(int256(-100)));
+ assertEq(helper.toInt128(v_int_small_pos), 100);
+ assertEq(helper.toInt64(v_int_small_neg), -100);
+ assertEq(helper.toInt32(v_int_small_pos), 100);
+ assertEq(helper.toInt16(v_int_small_neg), -100);
+ assertEq(helper.toInt8(v_int_small_pos), 100);
+
+ // Int array downcasting
+ int256[] memory small_ints = new int256[](2);
+ small_ints[0] = -10;
+ small_ints[1] = 20;
+ Variable memory intArraySmall = Variable(Type(TypeKind.Int256, true), abi.encode(small_ints));
+ int8[] memory i8_array = helper.toInt8Array(intArraySmall);
+ assertEq(i8_array[0], -10);
+ assertEq(i8_array[1], 20);
+ }
+
+ // -- REVERT CASES ---------------------------------------------------------
+
+ function testRevert_NotInitialized() public {
+ vm.expectRevert(LibVariable.NotInitialized.selector);
+ helper.toBool(uninitVar);
+
+ vm.expectRevert(LibVariable.NotInitialized.selector);
+ helper.toAddressArray(uninitVar);
+ }
+
+ function testRevert_assertExists() public {
+ vm.expectRevert(LibVariable.NotInitialized.selector);
+ helper.assertExists(uninitVar);
+ }
+
+ function testRevert_TypeMismatch() public {
+ // Single values
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "uint256", "bool"));
+ helper.toUint256(boolVar);
+
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "address", "string"));
+ helper.toAddress(stringVar);
+
+ // Arrays
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "uint256[]", "bool[]"));
+ helper.toUint256Array(boolArrayVar);
+
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "address[]", "string[]"));
+ helper.toAddressArray(stringArrayVar);
+
+ // Single value to array
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "bool[]", "bool"));
+ helper.toBoolArray(boolVar);
+
+ // Array to single value
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "bool", "bool[]"));
+ helper.toBool(boolArrayVar);
+
+ // assertEq reverts
+ vm.expectRevert(abi.encodeWithSelector(LibVariable.TypeMismatch.selector, "uint256", "bool"));
+ helper.assertEq(boolVar.ty, Type(TypeKind.Uint256, false));
+ }
+
+ function testRevert_UnsafeCast() public {
+ // uint overflow
+ Variable memory uintLarge = Variable(Type(TypeKind.Uint256, false), abi.encode(uint256(type(uint128).max) + 1));
+ expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value does not fit in 'uint128'");
+ vm.expectRevert(expectedErr);
+ helper.toUint128(uintLarge);
+
+ // int overflow
+ Variable memory intLarge = Variable(Type(TypeKind.Int256, false), abi.encode(int256(type(int128).max) + 1));
+ expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value does not fit in 'int128'");
+
+ vm.expectRevert(expectedErr);
+ helper.toInt128(intLarge);
+
+ // int underflow
+ Variable memory intSmall = Variable(Type(TypeKind.Int256, false), abi.encode(int256(type(int128).min) - 1));
+ expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value does not fit in 'int128'");
+
+ vm.expectRevert(expectedErr);
+ helper.toInt128(intSmall);
+
+ // uint array overflow
+ uint256[] memory uintArray = new uint256[](2);
+ uintArray[0] = 10;
+ uintArray[1] = uint256(type(uint64).max) + 1;
+ Variable memory uintArrayLarge = Variable(Type(TypeKind.Uint256, true), abi.encode(uintArray));
+ expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value in array does not fit in 'uint64'");
+
+ vm.expectRevert(expectedErr);
+ helper.toUint64Array(uintArrayLarge);
+
+ // int array overflow
+ int256[] memory intArray = new int256[](2);
+ intArray[0] = 10;
+ intArray[1] = int256(type(int64).max) + 1;
+ Variable memory intArrayLarge = Variable(Type(TypeKind.Int256, true), abi.encode(intArray));
+ expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value in array does not fit in 'int64'");
+
+ vm.expectRevert(expectedErr);
+ helper.toInt64Array(intArrayLarge);
+
+ // int array underflow
+ intArray[0] = 10;
+ intArray[1] = int256(type(int64).min) - 1;
+ Variable memory intArraySmall = Variable(Type(TypeKind.Int256, true), abi.encode(intArray));
+ expectedErr = abi.encodeWithSelector(LibVariable.UnsafeCast.selector, "value in array does not fit in 'int64'");
+
+ vm.expectRevert(expectedErr);
+ helper.toInt64Array(intArraySmall);
+ }
+}
+
+/// @dev We must use an external helper contract to ensure proper call depth for `vm.expectRevert`,
+/// as direct library calls are inlined by the compiler, causing call depth issues.
+contract LibVariableHelper {
+ using LibVariable for Type;
+ using LibVariable for TypeKind;
+
+ // Assertions
+ function assertExists(Variable memory v) external pure {
+ v.assertExists();
+ }
+
+ function assertEq(Type memory t1, Type memory t2) external pure {
+ t1.assertEq(t2);
+ }
+
+ // Single Value Coercion
+ function toBool(Variable memory v) external pure returns (bool) {
+ return v.toBool();
+ }
+
+ function toAddress(Variable memory v) external pure returns (address) {
+ return v.toAddress();
+ }
+
+ function toBytes32(Variable memory v) external pure returns (bytes32) {
+ return v.toBytes32();
+ }
+
+ function toUint256(Variable memory v) external pure returns (uint256) {
+ return v.toUint256();
+ }
+
+ function toInt256(Variable memory v) external pure returns (int256) {
+ return v.toInt256();
+ }
+
+ function toString(Variable memory v) external pure returns (string memory) {
+ return v.toString();
+ }
+
+ function toBytes(Variable memory v) external pure returns (bytes memory) {
+ return v.toBytes();
+ }
+
+ // Array Coercion
+ function toBoolArray(Variable memory v) external pure returns (bool[] memory) {
+ return v.toBoolArray();
+ }
+
+ function toAddressArray(Variable memory v) external pure returns (address[] memory) {
+ return v.toAddressArray();
+ }
+
+ function toBytes32Array(Variable memory v) external pure returns (bytes32[] memory) {
+ return v.toBytes32Array();
+ }
+
+ function toUint256Array(Variable memory v) external pure returns (uint256[] memory) {
+ return v.toUint256Array();
+ }
+
+ function toInt256Array(Variable memory v) external pure returns (int256[] memory) {
+ return v.toInt256Array();
+ }
+
+ function toStringArray(Variable memory v) external pure returns (string[] memory) {
+ return v.toStringArray();
+ }
+
+ function toBytesArray(Variable memory v) external pure returns (bytes[] memory) {
+ return v.toBytesArray();
+ }
+
+ // Uint Downcasting
+ function toUint128(Variable memory v) external pure returns (uint128) {
+ return v.toUint128();
+ }
+
+ function toUint64(Variable memory v) external pure returns (uint64) {
+ return v.toUint64();
+ }
+
+ function toUint32(Variable memory v) external pure returns (uint32) {
+ return v.toUint32();
+ }
+
+ function toUint16(Variable memory v) external pure returns (uint16) {
+ return v.toUint16();
+ }
+
+ function toUint8(Variable memory v) external pure returns (uint8) {
+ return v.toUint8();
+ }
+
+ // Int Downcasting
+ function toInt128(Variable memory v) external pure returns (int128) {
+ return v.toInt128();
+ }
+
+ function toInt64(Variable memory v) external pure returns (int64) {
+ return v.toInt64();
+ }
+
+ function toInt32(Variable memory v) external pure returns (int32) {
+ return v.toInt32();
+ }
+
+ function toInt16(Variable memory v) external pure returns (int16) {
+ return v.toInt16();
+ }
+
+ function toInt8(Variable memory v) external pure returns (int8) {
+ return v.toInt8();
+ }
+
+ // Uint Array Downcasting
+ function toUint128Array(Variable memory v) external pure returns (uint128[] memory) {
+ return v.toUint128Array();
+ }
+
+ function toUint64Array(Variable memory v) external pure returns (uint64[] memory) {
+ return v.toUint64Array();
+ }
+
+ function toUint32Array(Variable memory v) external pure returns (uint32[] memory) {
+ return v.toUint32Array();
+ }
+
+ function toUint16Array(Variable memory v) external pure returns (uint16[] memory) {
+ return v.toUint16Array();
+ }
+
+ function toUint8Array(Variable memory v) external pure returns (uint8[] memory) {
+ return v.toUint8Array();
+ }
+
+ // Int Array Downcasting
+ function toInt128Array(Variable memory v) external pure returns (int128[] memory) {
+ return v.toInt128Array();
+ }
+
+ function toInt64Array(Variable memory v) external pure returns (int64[] memory) {
+ return v.toInt64Array();
+ }
+
+ function toInt32Array(Variable memory v) external pure returns (int32[] memory) {
+ return v.toInt32Array();
+ }
+
+ function toInt16Array(Variable memory v) external pure returns (int16[] memory) {
+ return v.toInt16Array();
+ }
+
+ function toInt8Array(Variable memory v) external pure returns (int8[] memory) {
+ return v.toInt8Array();
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdAssertions.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdAssertions.t.sol
new file mode 100644
index 000000000..acc0c1e81
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdAssertions.t.sol
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {StdAssertions} from "../src/StdAssertions.sol";
+import {Vm} from "../src/Vm.sol";
+
+interface VmInternal is Vm {
+ function _expectCheatcodeRevert(bytes memory message) external;
+}
+
+contract StdAssertionsTest is StdAssertions {
+ string constant errorMessage = "User provided message";
+ uint256 constant maxDecimals = 77;
+
+ bool constant SHOULD_REVERT = true;
+ bool constant SHOULD_RETURN = false;
+
+ bool constant STRICT_REVERT_DATA = true;
+ bool constant NON_STRICT_REVERT_DATA = false;
+
+ VmInternal constant vm = VmInternal(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function testFuzz_AssertEqCall_Return_Pass(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory returnData,
+ bool strictRevertData
+ ) external {
+ address targetA = address(new TestMockCall(returnData, SHOULD_RETURN));
+ address targetB = address(new TestMockCall(returnData, SHOULD_RETURN));
+
+ assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
+ }
+
+ function testFuzz_RevertWhenCalled_AssertEqCall_Return_Fail(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory returnDataA,
+ bytes memory returnDataB,
+ bool strictRevertData
+ ) external {
+ vm.assume(keccak256(returnDataA) != keccak256(returnDataB));
+
+ address targetA = address(new TestMockCall(returnDataA, SHOULD_RETURN));
+ address targetB = address(new TestMockCall(returnDataB, SHOULD_RETURN));
+
+ vm._expectCheatcodeRevert(
+ bytes(
+ string.concat(
+ "Call return data does not match: ", vm.toString(returnDataA), " != ", vm.toString(returnDataB)
+ )
+ )
+ );
+ assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
+ }
+
+ function testFuzz_AssertEqCall_Revert_Pass(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory revertDataA,
+ bytes memory revertDataB
+ ) external {
+ address targetA = address(new TestMockCall(revertDataA, SHOULD_REVERT));
+ address targetB = address(new TestMockCall(revertDataB, SHOULD_REVERT));
+
+ assertEqCall(targetA, callDataA, targetB, callDataB, NON_STRICT_REVERT_DATA);
+ }
+
+ function testFuzz_RevertWhenCalled_AssertEqCall_Revert_Fail(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory revertDataA,
+ bytes memory revertDataB
+ ) external {
+ vm.assume(keccak256(revertDataA) != keccak256(revertDataB));
+
+ address targetA = address(new TestMockCall(revertDataA, SHOULD_REVERT));
+ address targetB = address(new TestMockCall(revertDataB, SHOULD_REVERT));
+
+ vm._expectCheatcodeRevert(
+ bytes(
+ string.concat(
+ "Call revert data does not match: ", vm.toString(revertDataA), " != ", vm.toString(revertDataB)
+ )
+ )
+ );
+ assertEqCall(targetA, callDataA, targetB, callDataB, STRICT_REVERT_DATA);
+ }
+
+ function testFuzz_RevertWhenCalled_AssertEqCall_Fail(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory returnDataA,
+ bytes memory returnDataB,
+ bool strictRevertData
+ ) external {
+ address targetA = address(new TestMockCall(returnDataA, SHOULD_RETURN));
+ address targetB = address(new TestMockCall(returnDataB, SHOULD_REVERT));
+
+ vm.expectRevert(bytes("assertion failed"));
+ this.assertEqCallExternal(targetA, callDataA, targetB, callDataB, strictRevertData);
+
+ vm.expectRevert(bytes("assertion failed"));
+ this.assertEqCallExternal(targetB, callDataB, targetA, callDataA, strictRevertData);
+ }
+
+ // Helper function to test outcome of assertEqCall via `expect` cheatcodes
+ function assertEqCallExternal(
+ address targetA,
+ bytes memory callDataA,
+ address targetB,
+ bytes memory callDataB,
+ bool strictRevertData
+ ) public {
+ assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
+ }
+}
+
+contract TestMockCall {
+ bytes returnData;
+ bool shouldRevert;
+
+ constructor(bytes memory returnData_, bool shouldRevert_) {
+ returnData = returnData_;
+ shouldRevert = shouldRevert_;
+ }
+
+ fallback() external payable {
+ bytes memory returnData_ = returnData;
+
+ if (shouldRevert) {
+ assembly {
+ revert(add(returnData_, 0x20), mload(returnData_))
+ }
+ } else {
+ assembly {
+ return(add(returnData_, 0x20), mload(returnData_))
+ }
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdChains.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdChains.t.sol
new file mode 100644
index 000000000..9522b37d0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdChains.t.sol
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test} from "../src/Test.sol";
+
+contract StdChainsMock is Test {
+ function exposed_getChain(string memory chainAlias) public returns (Chain memory) {
+ return getChain(chainAlias);
+ }
+
+ function exposed_getChain(uint256 chainId) public returns (Chain memory) {
+ return getChain(chainId);
+ }
+
+ function exposed_setChain(string memory chainAlias, ChainData memory chainData) public {
+ setChain(chainAlias, chainData);
+ }
+
+ function exposed_setFallbackToDefaultRpcUrls(bool useDefault) public {
+ setFallbackToDefaultRpcUrls(useDefault);
+ }
+}
+
+contract StdChainsTest is Test {
+ function test_ChainRpcInitialization() public {
+ // RPCs specified in `foundry.toml` should be updated.
+ assertEq(getChain(1).rpcUrl, "https://eth.merkle.io");
+ assertEq(getChain("optimism_sepolia").rpcUrl, "https://sepolia.optimism.io/");
+ assertEq(getChain("arbitrum_one_sepolia").rpcUrl, "https://sepolia-rollup.arbitrum.io/rpc/");
+
+ // Environment variables should be the next fallback
+ assertEq(getChain("arbitrum_nova").rpcUrl, "https://nova.arbitrum.io/rpc");
+ vm.setEnv("ARBITRUM_NOVA_RPC_URL", "myoverride");
+ assertEq(getChain("arbitrum_nova").rpcUrl, "myoverride");
+ vm.setEnv("ARBITRUM_NOVA_RPC_URL", "https://nova.arbitrum.io/rpc");
+
+ // Cannot override RPCs defined in `foundry.toml`
+ vm.setEnv("MAINNET_RPC_URL", "myoverride2");
+ assertEq(getChain("mainnet").rpcUrl, "https://eth.merkle.io");
+
+ // Other RPCs should remain unchanged.
+ assertEq(getChain(31337).rpcUrl, "http://127.0.0.1:8545");
+ assertEq(getChain("sepolia").rpcUrl, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001");
+ }
+
+ // Named with a leading underscore to clarify this is not intended to be run as a normal test,
+ // and is intended to be used in the below `test_Rpcs` test.
+ function _testRpc(string memory rpcAlias) internal {
+ string memory rpcUrl = getChain(rpcAlias).rpcUrl;
+ vm.createSelectFork(rpcUrl);
+ }
+
+ // Ensure we can connect to the default RPC URL for each chain.
+ // Currently commented out since this is slow and public RPCs are flaky, often resulting in failing CI.
+ // function test_Rpcs() public {
+ // _testRpc("mainnet");
+ // _testRpc("sepolia");
+ // _testRpc("holesky");
+ // _testRpc("optimism");
+ // _testRpc("optimism_sepolia");
+ // _testRpc("arbitrum_one");
+ // _testRpc("arbitrum_one_sepolia");
+ // _testRpc("arbitrum_nova");
+ // _testRpc("polygon");
+ // _testRpc("polygon_amoy");
+ // _testRpc("avalanche");
+ // _testRpc("avalanche_fuji");
+ // _testRpc("bnb_smart_chain");
+ // _testRpc("bnb_smart_chain_testnet");
+ // _testRpc("gnosis_chain");
+ // _testRpc("moonbeam");
+ // _testRpc("moonriver");
+ // _testRpc("moonbase");
+ // _testRpc("base_sepolia");
+ // _testRpc("base");
+ // _testRpc("blast_sepolia");
+ // _testRpc("blast");
+ // _testRpc("fantom_opera");
+ // _testRpc("fantom_opera_testnet");
+ // _testRpc("fraxtal");
+ // _testRpc("fraxtal_testnet");
+ // _testRpc("berachain_bartio_testnet");
+ // _testRpc("flare");
+ // _testRpc("flare_coston2");
+ // }
+
+ function test_RevertIf_ChainNotFound() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(string): Chain with alias \"does_not_exist\" not found.");
+ stdChainsMock.exposed_getChain("does_not_exist");
+ }
+
+ function test_RevertIf_SetChain_ChainIdExist_FirstTest() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains setChain(string,ChainData): Chain ID 31337 already used by \"anvil\".");
+ stdChainsMock.exposed_setChain("anvil2", ChainData("Anvil", 31337, "URL"));
+ }
+
+ function test_RevertIf_ChainBubbleUp() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ stdChainsMock.exposed_setChain("needs_undefined_env_var", ChainData("", 123456789, ""));
+ // Forge environment variable error.
+ vm.expectRevert();
+ stdChainsMock.exposed_getChain("needs_undefined_env_var");
+ }
+
+ function test_RevertIf_SetChain_ChainIdExists_SecondTest() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ stdChainsMock.exposed_setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
+
+ vm.expectRevert('StdChains setChain(string,ChainData): Chain ID 123456789 already used by "custom_chain".');
+
+ stdChainsMock.exposed_setChain("another_custom_chain", ChainData("", 123456789, ""));
+ }
+
+ function test_SetChain() public {
+ setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
+ Chain memory customChain = getChain("custom_chain");
+ assertEq(customChain.name, "Custom Chain");
+ assertEq(customChain.chainId, 123456789);
+ assertEq(customChain.chainAlias, "custom_chain");
+ assertEq(customChain.rpcUrl, "https://custom.chain/");
+ Chain memory chainById = getChain(123456789);
+ assertEq(chainById.name, customChain.name);
+ assertEq(chainById.chainId, customChain.chainId);
+ assertEq(chainById.chainAlias, customChain.chainAlias);
+ assertEq(chainById.rpcUrl, customChain.rpcUrl);
+ customChain.name = "Another Custom Chain";
+ customChain.chainId = 987654321;
+ setChain("another_custom_chain", customChain);
+ Chain memory anotherCustomChain = getChain("another_custom_chain");
+ assertEq(anotherCustomChain.name, "Another Custom Chain");
+ assertEq(anotherCustomChain.chainId, 987654321);
+ assertEq(anotherCustomChain.chainAlias, "another_custom_chain");
+ assertEq(anotherCustomChain.rpcUrl, "https://custom.chain/");
+ // Verify the first chain data was not overwritten
+ chainById = getChain(123456789);
+ assertEq(chainById.name, "Custom Chain");
+ assertEq(chainById.chainId, 123456789);
+ }
+
+ function test_RevertIf_SetEmptyAlias() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains setChain(string,ChainData): Chain alias cannot be the empty string.");
+ stdChainsMock.exposed_setChain("", ChainData("", 123456789, ""));
+ }
+
+ function test_RevertIf_SetNoChainId0() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains setChain(string,ChainData): Chain ID cannot be 0.");
+ stdChainsMock.exposed_setChain("alias", ChainData("", 0, ""));
+ }
+
+ function test_RevertIf_GetNoChainId0() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(uint256): Chain ID cannot be 0.");
+ stdChainsMock.exposed_getChain(0);
+ }
+
+ function test_RevertIf_GetNoEmptyAlias() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(string): Chain alias cannot be the empty string.");
+ stdChainsMock.exposed_getChain("");
+ }
+
+ function test_RevertIf_ChainNotInitialized() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(string): Chain with alias \"no_such_alias\" not found.");
+ stdChainsMock.exposed_getChain("no_such_alias");
+ }
+
+ function test_RevertIf_ChainAliasNotFound() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(uint256): Chain with ID 321 not found.");
+
+ stdChainsMock.exposed_getChain(321);
+ }
+
+ function test_SetChain_ExistingOne() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
+ assertEq(getChain(123456789).chainId, 123456789);
+
+ setChain("custom_chain", ChainData("Modified Chain", 9999999999999999999, "https://modified.chain/"));
+ vm.expectRevert("StdChains getChain(uint256): Chain with ID 123456789 not found.");
+ stdChainsMock.exposed_getChain(123456789);
+
+ Chain memory modifiedChain = getChain(9999999999999999999);
+ assertEq(modifiedChain.name, "Modified Chain");
+ assertEq(modifiedChain.chainId, 9999999999999999999);
+ assertEq(modifiedChain.rpcUrl, "https://modified.chain/");
+ }
+
+ function test_RevertIf_DontUseDefaultRpcUrl() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ // Should error if default RPCs flag is set to false.
+ stdChainsMock.exposed_setFallbackToDefaultRpcUrls(false);
+ vm.expectRevert();
+ stdChainsMock.exposed_getChain(31337);
+ vm.expectRevert();
+ stdChainsMock.exposed_getChain("sepolia");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdCheats.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdCheats.t.sol
new file mode 100644
index 000000000..57dbcc291
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdCheats.t.sol
@@ -0,0 +1,639 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {StdCheats} from "../src/StdCheats.sol";
+import {Test} from "../src/Test.sol";
+import {stdJson} from "../src/StdJson.sol";
+import {stdToml} from "../src/StdToml.sol";
+import {IERC20} from "../src/interfaces/IERC20.sol";
+
+contract StdCheatsTest is Test {
+ Bar test;
+
+ using stdJson for string;
+
+ function setUp() public {
+ test = new Bar();
+ }
+
+ function test_Skip() public {
+ vm.warp(100);
+ skip(25);
+ assertEq(block.timestamp, 125);
+ }
+
+ function test_Rewind() public {
+ vm.warp(100);
+ rewind(25);
+ assertEq(block.timestamp, 75);
+ }
+
+ function test_Hoax() public {
+ hoax(address(1337));
+ test.bar{value: 100}(address(1337));
+ }
+
+ function test_HoaxOrigin() public {
+ hoax(address(1337), address(1337));
+ test.origin{value: 100}(address(1337));
+ }
+
+ function test_HoaxDifferentAddresses() public {
+ hoax(address(1337), address(7331));
+ test.origin{value: 100}(address(1337), address(7331));
+ }
+
+ function test_StartHoax() public {
+ startHoax(address(1337));
+ test.bar{value: 100}(address(1337));
+ test.bar{value: 100}(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+
+ function test_StartHoaxOrigin() public {
+ startHoax(address(1337), address(1337));
+ test.origin{value: 100}(address(1337));
+ test.origin{value: 100}(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+
+ function test_ChangePrankMsgSender() public {
+ vm.startPrank(address(1337));
+ test.bar(address(1337));
+ changePrank(address(0xdead));
+ test.bar(address(0xdead));
+ changePrank(address(1337));
+ test.bar(address(1337));
+ vm.stopPrank();
+ }
+
+ function test_ChangePrankMsgSenderAndTxOrigin() public {
+ vm.startPrank(address(1337), address(1338));
+ test.origin(address(1337), address(1338));
+ changePrank(address(0xdead), address(0xbeef));
+ test.origin(address(0xdead), address(0xbeef));
+ changePrank(address(1337), address(1338));
+ test.origin(address(1337), address(1338));
+ vm.stopPrank();
+ }
+
+ function test_MakeAccountEquivalence() public {
+ Account memory account = makeAccount("1337");
+ (address addr, uint256 key) = makeAddrAndKey("1337");
+ assertEq(account.addr, addr);
+ assertEq(account.key, key);
+ }
+
+ function test_MakeAddrEquivalence() public {
+ (address addr,) = makeAddrAndKey("1337");
+ assertEq(makeAddr("1337"), addr);
+ }
+
+ function test_MakeAddrSigning() public {
+ (address addr, uint256 key) = makeAddrAndKey("1337");
+ bytes32 hash = keccak256("some_message");
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash);
+ assertEq(ecrecover(hash, v, r, s), addr);
+ }
+
+ function test_Deal() public {
+ deal(address(this), 1 ether);
+ assertEq(address(this).balance, 1 ether);
+ }
+
+ function test_DealToken() public {
+ Bar barToken = new Bar();
+ address bar = address(barToken);
+ deal(bar, address(this), 10000e18);
+ assertEq(barToken.balanceOf(address(this)), 10000e18);
+ }
+
+ function test_DealTokenAdjustTotalSupply() public {
+ Bar barToken = new Bar();
+ address bar = address(barToken);
+ deal(bar, address(this), 10000e18, true);
+ assertEq(barToken.balanceOf(address(this)), 10000e18);
+ assertEq(barToken.totalSupply(), 20000e18);
+ deal(bar, address(this), 0, true);
+ assertEq(barToken.balanceOf(address(this)), 0);
+ assertEq(barToken.totalSupply(), 10000e18);
+ }
+
+ function test_DealERC1155Token() public {
+ BarERC1155 barToken = new BarERC1155();
+ address bar = address(barToken);
+ dealERC1155(bar, address(this), 0, 10000e18, false);
+ assertEq(barToken.balanceOf(address(this), 0), 10000e18);
+ }
+
+ function test_DealERC1155TokenAdjustTotalSupply() public {
+ BarERC1155 barToken = new BarERC1155();
+ address bar = address(barToken);
+ dealERC1155(bar, address(this), 0, 10000e18, true);
+ assertEq(barToken.balanceOf(address(this), 0), 10000e18);
+ assertEq(barToken.totalSupply(0), 20000e18);
+ dealERC1155(bar, address(this), 0, 0, true);
+ assertEq(barToken.balanceOf(address(this), 0), 0);
+ assertEq(barToken.totalSupply(0), 10000e18);
+ }
+
+ function test_DealERC721Token() public {
+ BarERC721 barToken = new BarERC721();
+ address bar = address(barToken);
+ dealERC721(bar, address(2), 1);
+ assertEq(barToken.balanceOf(address(2)), 1);
+ assertEq(barToken.balanceOf(address(1)), 0);
+ dealERC721(bar, address(1), 2);
+ assertEq(barToken.balanceOf(address(1)), 1);
+ assertEq(barToken.balanceOf(bar), 1);
+ }
+
+ function test_DeployCode() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""));
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ }
+
+ function test_DestroyAccount() public {
+ // deploy something to destroy it
+ BarERC721 barToken = new BarERC721();
+ address bar = address(barToken);
+ vm.setNonce(bar, 10);
+ deal(bar, 100);
+
+ uint256 prevThisBalance = address(this).balance;
+ uint256 size;
+ assembly {
+ size := extcodesize(bar)
+ }
+
+ assertGt(size, 0);
+ assertEq(bar.balance, 100);
+ assertEq(vm.getNonce(bar), 10);
+
+ destroyAccount(bar, address(this));
+ assembly {
+ size := extcodesize(bar)
+ }
+ assertEq(address(this).balance, prevThisBalance + 100);
+ assertEq(vm.getNonce(bar), 0);
+ assertEq(size, 0);
+ assertEq(bar.balance, 0);
+ }
+
+ function test_DeployCodeNoArgs() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar");
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ }
+
+ function test_DeployCodeVal() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""), 1 ether);
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ assertEq(deployed.balance, 1 ether);
+ }
+
+ function test_DeployCodeValNoArgs() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar", 1 ether);
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ assertEq(deployed.balance, 1 ether);
+ }
+
+ // We need this so we can call "this.deployCode" rather than "deployCode" directly
+ function deployCodeHelper(string memory what) external {
+ deployCode(what);
+ }
+
+ function test_RevertIf_DeployCodeFail() public {
+ vm.expectRevert(bytes("StdCheats deployCode(string): Deployment failed."));
+ this.deployCodeHelper("StdCheats.t.sol:RevertingContract");
+ }
+
+ function getCode(address who) internal view returns (bytes memory o_code) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ // retrieve the size of the code, this needs assembly
+ let size := extcodesize(who)
+ // allocate output byte array - this could also be done without assembly
+ // by using o_code = new bytes(size)
+ o_code := mload(0x40)
+ // new "memory end" including padding
+ mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
+ // store length in memory
+ mstore(o_code, size)
+ // actually retrieve the code, this needs assembly
+ extcodecopy(who, add(o_code, 0x20), 0, size)
+ }
+ }
+
+ function test_DeriveRememberKey() public {
+ string memory mnemonic = "test test test test test test test test test test test junk";
+
+ (address deployer, uint256 privateKey) = deriveRememberKey(mnemonic, 0);
+ assertEq(deployer, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
+ assertEq(privateKey, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80);
+ }
+
+ function test_BytesToUint() public pure {
+ assertEq(3, bytesToUint_test(hex"03"));
+ assertEq(2, bytesToUint_test(hex"02"));
+ assertEq(255, bytesToUint_test(hex"ff"));
+ assertEq(29625, bytesToUint_test(hex"73b9"));
+ }
+
+ function test_ParseJsonTxDetail() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ string memory json = vm.readFile(path);
+ bytes memory transactionDetails = json.parseRaw(".transactions[0].tx");
+ RawTx1559Detail memory rawTxDetail = abi.decode(transactionDetails, (RawTx1559Detail));
+ Tx1559Detail memory txDetail = rawToConvertedEIP1559Detail(rawTxDetail);
+ assertEq(txDetail.from, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
+ assertEq(txDetail.to, 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512);
+ assertEq(
+ txDetail.data,
+ hex"23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"
+ );
+ assertEq(txDetail.nonce, 3);
+ assertEq(txDetail.txType, 2);
+ assertEq(txDetail.gas, 29625);
+ assertEq(txDetail.value, 0);
+ }
+
+ function test_ReadEIP1559Transaction() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ uint256 index = 0;
+ Tx1559 memory transaction = readTx1559(path, index);
+ transaction;
+ }
+
+ function test_ReadEIP1559Transactions() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ Tx1559[] memory transactions = readTx1559s(path);
+ transactions;
+ }
+
+ function test_ReadReceipt() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ uint256 index = 5;
+ Receipt memory receipt = readReceipt(path, index);
+ assertEq(
+ receipt.logsBloom,
+ hex"00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100"
+ );
+ }
+
+ function test_ReadReceipts() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ Receipt[] memory receipts = readReceipts(path);
+ receipts;
+ }
+
+ function test_GasMeteringModifier() public {
+ uint256 gas_start_normal = gasleft();
+ addInLoop();
+ uint256 gas_used_normal = gas_start_normal - gasleft();
+
+ uint256 gas_start_single = gasleft();
+ addInLoopNoGas();
+ uint256 gas_used_single = gas_start_single - gasleft();
+
+ uint256 gas_start_double = gasleft();
+ addInLoopNoGasNoGas();
+ uint256 gas_used_double = gas_start_double - gasleft();
+
+ assertTrue(gas_used_double + gas_used_single < gas_used_normal);
+ }
+
+ function addInLoop() internal pure returns (uint256) {
+ uint256 b;
+ for (uint256 i; i < 10000; i++) {
+ b += i;
+ }
+ return b;
+ }
+
+ function addInLoopNoGas() internal noGasMetering returns (uint256) {
+ return addInLoop();
+ }
+
+ function addInLoopNoGasNoGas() internal noGasMetering returns (uint256) {
+ return addInLoopNoGas();
+ }
+
+ function bytesToUint_test(bytes memory b) private pure returns (uint256) {
+ uint256 number;
+ for (uint256 i = 0; i < b.length; i++) {
+ number = number + uint256(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1))));
+ }
+ return number;
+ }
+
+ function testFuzz_AssumeAddressIsNot(address addr) external {
+ // skip over Payable and NonPayable enums
+ for (uint8 i = 2; i < uint8(type(AddressType).max); i++) {
+ assumeAddressIsNot(addr, AddressType(i));
+ }
+ assertTrue(addr != address(0));
+ assertTrue(addr < address(1) || addr > address(9));
+ assertTrue(addr != address(vm) || addr != 0x000000000000000000636F6e736F6c652e6c6f67);
+ }
+
+ function test_AssumePayable() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+
+ // all should revert since these addresses are not payable
+
+ // VM address
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
+
+ // Console address
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumePayable(0x000000000000000000636F6e736F6c652e6c6f67);
+
+ // Create2Deployer
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
+
+ // all should pass since these addresses are payable
+
+ // vitalik.eth
+ stdCheatsMock.exposed_assumePayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);
+
+ // mock payable contract
+ MockContractPayable cp = new MockContractPayable();
+ stdCheatsMock.exposed_assumePayable(address(cp));
+ }
+
+ function test_AssumeNotPayable() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+
+ // all should pass since these addresses are not payable
+
+ // VM address
+ stdCheatsMock.exposed_assumeNotPayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
+
+ // Console address
+ stdCheatsMock.exposed_assumeNotPayable(0x000000000000000000636F6e736F6c652e6c6f67);
+
+ // Create2Deployer
+ stdCheatsMock.exposed_assumeNotPayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
+
+ // all should revert since these addresses are payable
+
+ // vitalik.eth
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotPayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);
+
+ // mock payable contract
+ MockContractPayable cp = new MockContractPayable();
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotPayable(address(cp));
+ }
+
+ function testFuzz_AssumeNotPrecompile(address addr) external {
+ assumeNotPrecompile(addr, getChain("optimism_sepolia").chainId);
+ assertTrue(
+ addr < address(1) || (addr > address(9) && addr < address(0x4200000000000000000000000000000000000000))
+ || addr > address(0x4200000000000000000000000000000000000800)
+ );
+ }
+
+ function testFuzz_AssumeNotForgeAddress(address addr) external pure {
+ assumeNotForgeAddress(addr);
+ assertTrue(
+ addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
+ && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
+ );
+ }
+
+ function test_RevertIf_CannotDeployCodeTo() external {
+ vm.expectRevert("StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
+ this._revertDeployCodeTo();
+ }
+
+ function _revertDeployCodeTo() external {
+ deployCodeTo("StdCheats.t.sol:RevertingContract", address(0));
+ }
+
+ function test_DeployCodeTo() external {
+ address arbitraryAddress = makeAddr("arbitraryAddress");
+
+ deployCodeTo(
+ "StdCheats.t.sol:MockContractWithConstructorArgs",
+ abi.encode(uint256(6), true, bytes20(arbitraryAddress)),
+ 1 ether,
+ arbitraryAddress
+ );
+
+ MockContractWithConstructorArgs ct = MockContractWithConstructorArgs(arbitraryAddress);
+
+ assertEq(arbitraryAddress.balance, 1 ether);
+ assertEq(ct.x(), 6);
+ assertTrue(ct.y());
+ assertEq(ct.z(), bytes20(arbitraryAddress));
+ }
+}
+
+contract StdCheatsMock is StdCheats {
+ function exposed_assumePayable(address addr) external {
+ assumePayable(addr);
+ }
+
+ function exposed_assumeNotPayable(address addr) external {
+ assumeNotPayable(addr);
+ }
+
+ // We deploy a mock version so we can properly test expected reverts.
+ function exposed_assumeNotBlacklisted(address token, address addr) external view {
+ return assumeNotBlacklisted(token, addr);
+ }
+}
+
+contract StdCheatsForkTest is Test {
+ address internal constant USDC_BLACKLISTED_USER = 0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD;
+ address internal constant USDT_BLACKLISTED_USER = 0x8f8a8F4B54a2aAC7799d7bc81368aC27b852822A;
+
+ MockUSDT public USDT;
+ MockUSDC public USDC;
+
+ function setUp() public {
+ USDT = new MockUSDT();
+ USDC = new MockUSDC();
+
+ USDC.setBlacklisted(USDC_BLACKLISTED_USER, true);
+ USDT.setBlacklisted(USDT_BLACKLISTED_USER, true);
+ }
+
+ function test_RevertIf_CannotAssumeNoBlacklisted_EOA() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+ address eoa = vm.addr({privateKey: 1});
+ vm.expectRevert("StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
+ stdCheatsMock.exposed_assumeNotBlacklisted(eoa, address(0));
+ }
+
+ function testFuzz_AssumeNotBlacklisted_TokenWithoutBlacklist(address addr) external view {
+ assumeNotBlacklisted(address(USDC), addr);
+ assumeNotBlacklisted(address(USDT), addr);
+ assertTrue(true);
+ }
+
+ function test_RevertIf_AssumeNoBlacklisted_USDC() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotBlacklisted(address(USDC), USDC_BLACKLISTED_USER);
+ }
+
+ function testFuzz_AssumeNotBlacklisted_USDC(address addr) external view {
+ assumeNotBlacklisted(address(USDC), addr);
+ assertFalse(USDCLike(USDC).isBlacklisted(addr));
+ }
+
+ function test_RevertIf_AssumeNoBlacklisted_USDT() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotBlacklisted(address(USDT), USDT_BLACKLISTED_USER);
+ }
+
+ function testFuzz_AssumeNotBlacklisted_USDT(address addr) external view {
+ assumeNotBlacklisted(address(USDT), addr);
+ assertFalse(USDTLike(USDT).isBlackListed(addr));
+ }
+}
+
+/// @dev https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#readProxyContract
+interface USDCLike {
+ function isBlacklisted(address) external view returns (bool);
+}
+
+/// @dev https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#readContract
+interface USDTLike {
+ function isBlackListed(address) external view returns (bool);
+}
+
+contract MockUSDT is USDTLike {
+ mapping(address => bool) private blacklist;
+
+ function isBlackListed(address addr) external view returns (bool) {
+ return blacklist[addr];
+ }
+
+ function setBlacklisted(address addr, bool value) external {
+ blacklist[addr] = value;
+ }
+}
+
+contract MockUSDC is USDCLike {
+ mapping(address => bool) private blacklist;
+
+ function isBlacklisted(address addr) external view returns (bool) {
+ return blacklist[addr];
+ }
+
+ function setBlacklisted(address addr, bool value) external {
+ blacklist[addr] = value;
+ }
+}
+
+contract Bar {
+ constructor() payable {
+ /// `DEAL` STDCHEAT
+ totalSupply = 10000e18;
+ balanceOf[address(this)] = totalSupply;
+ }
+
+ /// `HOAX` and `CHANGEPRANK` STDCHEATS
+ function bar(address expectedSender) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ }
+
+ function origin(address expectedSender) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ require(tx.origin == expectedSender, "!prank");
+ }
+
+ function origin(address expectedSender, address expectedOrigin) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ require(tx.origin == expectedOrigin, "!prank");
+ }
+
+ /// `DEAL` STDCHEAT
+ mapping(address => uint256) public balanceOf;
+ uint256 public totalSupply;
+}
+
+contract BarERC1155 {
+ constructor() payable {
+ /// `DEALERC1155` STDCHEAT
+ _totalSupply[0] = 10000e18;
+ _balances[0][address(this)] = _totalSupply[0];
+ }
+
+ function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
+ return _balances[id][account];
+ }
+
+ function totalSupply(uint256 id) public view virtual returns (uint256) {
+ return _totalSupply[id];
+ }
+
+ /// `DEALERC1155` STDCHEAT
+ mapping(uint256 => mapping(address => uint256)) private _balances;
+ mapping(uint256 => uint256) private _totalSupply;
+}
+
+contract BarERC721 {
+ constructor() payable {
+ /// `DEALERC721` STDCHEAT
+ _owners[1] = address(1);
+ _balances[address(1)] = 1;
+ _owners[2] = address(this);
+ _owners[3] = address(this);
+ _balances[address(this)] = 2;
+ }
+
+ function balanceOf(address owner) public view virtual returns (uint256) {
+ return _balances[owner];
+ }
+
+ function ownerOf(uint256 tokenId) public view virtual returns (address) {
+ address owner = _owners[tokenId];
+ return owner;
+ }
+
+ mapping(uint256 => address) private _owners;
+ mapping(address => uint256) private _balances;
+}
+
+contract RevertingContract {
+ constructor() {
+ revert();
+ }
+}
+
+contract MockContractWithConstructorArgs {
+ uint256 public immutable x;
+ bool public y;
+ bytes20 public z;
+
+ constructor(uint256 _x, bool _y, bytes20 _z) payable {
+ x = _x;
+ y = _y;
+ z = _z;
+ }
+}
+
+contract MockContractPayable {
+ receive() external payable {}
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdConstants.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdConstants.t.sol
new file mode 100644
index 000000000..7a00530f4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdConstants.t.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {StdConstants} from "../src/StdConstants.sol";
+import {Test} from "../src/Test.sol";
+
+contract StdConstantsTest is Test {
+ function testVm() public view {
+ assertEq(StdConstants.VM.getBlockNumber(), 1);
+ }
+
+ function testVmDerivation() public pure {
+ assertEq(address(StdConstants.VM), address(uint160(uint256(keccak256("hevm cheat code")))));
+ }
+
+ function testConsoleDerivation() public pure {
+ assertEq(StdConstants.CONSOLE, address(uint160(uint88(bytes11("console.log")))));
+ }
+
+ function testDefaultSender() public view {
+ assertEq(StdConstants.DEFAULT_SENDER, msg.sender);
+ }
+
+ function testDefaultSenderDerivation() public pure {
+ assertEq(StdConstants.DEFAULT_SENDER, address(uint160(uint256(keccak256("foundry default caller")))));
+ }
+
+ function testDefaultTestContract() public {
+ assertEq(StdConstants.DEFAULT_TEST_CONTRACT, address(new Dummy()));
+ }
+
+ function testDefaultTestContractDerivation() public view {
+ assertEq(address(this), StdConstants.VM.computeCreateAddress(StdConstants.DEFAULT_SENDER, 1));
+ assertEq(StdConstants.DEFAULT_TEST_CONTRACT, StdConstants.VM.computeCreateAddress(address(this), 1));
+ }
+}
+
+contract Dummy {}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdError.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdError.t.sol
new file mode 100644
index 000000000..29803d5d5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdError.t.sol
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.0 <0.9.0;
+
+import {stdError} from "../src/StdError.sol";
+import {Test} from "../src/Test.sol";
+
+contract StdErrorsTest is Test {
+ ErrorsTest test;
+
+ function setUp() public {
+ test = new ErrorsTest();
+ }
+
+ function test_RevertIf_AssertionError() public {
+ vm.expectRevert(stdError.assertionError);
+ test.assertionError();
+ }
+
+ function test_RevertIf_ArithmeticError() public {
+ vm.expectRevert(stdError.arithmeticError);
+ test.arithmeticError(10);
+ }
+
+ function test_RevertIf_DivisionError() public {
+ vm.expectRevert(stdError.divisionError);
+ test.divError(0);
+ }
+
+ function test_RevertIf_ModError() public {
+ vm.expectRevert(stdError.divisionError);
+ test.modError(0);
+ }
+
+ function test_RevertIf_EnumConversionError() public {
+ vm.expectRevert(stdError.enumConversionError);
+ test.enumConversion(1);
+ }
+
+ function test_RevertIf_EncodeStgError() public {
+ vm.expectRevert(stdError.encodeStorageError);
+ test.encodeStgError();
+ }
+
+ function test_RevertIf_PopError() public {
+ vm.expectRevert(stdError.popError);
+ test.pop();
+ }
+
+ function test_RevertIf_IndexOOBError() public {
+ vm.expectRevert(stdError.indexOOBError);
+ test.indexOOBError(1);
+ }
+
+ function test_RevertIf_MemOverflowError() public {
+ vm.expectRevert(stdError.memOverflowError);
+ test.mem();
+ }
+
+ function test_RevertIf_InternError() public {
+ vm.expectRevert(stdError.zeroVarError);
+ test.intern();
+ }
+}
+
+contract ErrorsTest {
+ enum T {
+ T1
+ }
+
+ uint256[] public someArr;
+ bytes someBytes;
+
+ function assertionError() public pure {
+ assert(false);
+ }
+
+ function arithmeticError(uint256 a) public pure {
+ a -= 100;
+ }
+
+ function divError(uint256 a) public pure {
+ 100 / a;
+ }
+
+ function modError(uint256 a) public pure {
+ 100 % a;
+ }
+
+ function enumConversion(uint256 a) public pure {
+ T(a);
+ }
+
+ function encodeStgError() public {
+ /// @solidity memory-safe-assembly
+ assembly {
+ sstore(someBytes.slot, 1)
+ }
+ keccak256(someBytes);
+ }
+
+ function pop() public {
+ someArr.pop();
+ }
+
+ function indexOOBError(uint256 a) public pure {
+ uint256[] memory t = new uint256[](0);
+ t[a];
+ }
+
+ function mem() public pure {
+ uint256 l = 2 ** 256 / 32;
+ new uint256[](l);
+ }
+
+ function intern() public returns (uint256) {
+ function(uint256) internal returns (uint256) x;
+ x(2);
+ return 7;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdJson.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdJson.t.sol
new file mode 100644
index 000000000..6bedfcc9a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdJson.t.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, stdJson} from "../src/Test.sol";
+
+contract StdJsonTest is Test {
+ using stdJson for string;
+
+ string root;
+ string path;
+
+ function setUp() public {
+ root = vm.projectRoot();
+ path = string.concat(root, "/test/fixtures/test.json");
+ }
+
+ struct SimpleJson {
+ uint256 a;
+ string b;
+ }
+
+ struct NestedJson {
+ uint256 a;
+ string b;
+ SimpleJson c;
+ }
+
+ function test_readJson() public view {
+ string memory json = vm.readFile(path);
+ assertEq(json.readUint(".a"), 123);
+ }
+
+ function test_writeJson() public {
+ string memory json = "json";
+ json.serialize("a", uint256(123));
+ string memory semiFinal = json.serialize("b", string("test"));
+ string memory finalJson = json.serialize("c", semiFinal);
+ finalJson.write(path);
+
+ string memory json_ = vm.readFile(path);
+ bytes memory data = json_.parseRaw("$");
+ NestedJson memory decodedData = abi.decode(data, (NestedJson));
+
+ assertEq(decodedData.a, 123);
+ assertEq(decodedData.b, "test");
+ assertEq(decodedData.c.a, 123);
+ assertEq(decodedData.c.b, "test");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdMath.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdMath.t.sol
new file mode 100644
index 000000000..d1269a02a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdMath.t.sol
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.0 <0.9.0;
+
+import {stdMath} from "../src/StdMath.sol";
+import {Test, stdError} from "../src/Test.sol";
+
+contract StdMathMock is Test {
+ function exposed_percentDelta(uint256 a, uint256 b) public pure returns (uint256) {
+ return stdMath.percentDelta(a, b);
+ }
+
+ function exposed_percentDelta(int256 a, int256 b) public pure returns (uint256) {
+ return stdMath.percentDelta(a, b);
+ }
+}
+
+contract StdMathTest is Test {
+ function test_GetAbs() external pure {
+ assertEq(stdMath.abs(-50), 50);
+ assertEq(stdMath.abs(50), 50);
+ assertEq(stdMath.abs(-1337), 1337);
+ assertEq(stdMath.abs(0), 0);
+
+ assertEq(stdMath.abs(type(int256).min), (type(uint256).max >> 1) + 1);
+ assertEq(stdMath.abs(type(int256).max), (type(uint256).max >> 1));
+ }
+
+ function testFuzz_GetAbs(int256 a) external pure {
+ uint256 manualAbs = getAbs(a);
+
+ uint256 abs = stdMath.abs(a);
+
+ assertEq(abs, manualAbs);
+ }
+
+ function test_GetDelta_Uint() external pure {
+ assertEq(stdMath.delta(uint256(0), uint256(0)), 0);
+ assertEq(stdMath.delta(uint256(0), uint256(1337)), 1337);
+ assertEq(stdMath.delta(uint256(0), type(uint64).max), type(uint64).max);
+ assertEq(stdMath.delta(uint256(0), type(uint128).max), type(uint128).max);
+ assertEq(stdMath.delta(uint256(0), type(uint256).max), type(uint256).max);
+
+ assertEq(stdMath.delta(0, uint256(0)), 0);
+ assertEq(stdMath.delta(1337, uint256(0)), 1337);
+ assertEq(stdMath.delta(type(uint64).max, uint256(0)), type(uint64).max);
+ assertEq(stdMath.delta(type(uint128).max, uint256(0)), type(uint128).max);
+ assertEq(stdMath.delta(type(uint256).max, uint256(0)), type(uint256).max);
+
+ assertEq(stdMath.delta(1337, uint256(1337)), 0);
+ assertEq(stdMath.delta(type(uint256).max, type(uint256).max), 0);
+ assertEq(stdMath.delta(5000, uint256(1250)), 3750);
+ }
+
+ function testFuzz_GetDelta_Uint(uint256 a, uint256 b) external pure {
+ uint256 manualDelta = a > b ? a - b : b - a;
+
+ uint256 delta = stdMath.delta(a, b);
+
+ assertEq(delta, manualDelta);
+ }
+
+ function test_GetDelta_Int() external pure {
+ assertEq(stdMath.delta(int256(0), int256(0)), 0);
+ assertEq(stdMath.delta(int256(0), int256(1337)), 1337);
+ assertEq(stdMath.delta(int256(0), type(int64).max), type(uint64).max >> 1);
+ assertEq(stdMath.delta(int256(0), type(int128).max), type(uint128).max >> 1);
+ assertEq(stdMath.delta(int256(0), type(int256).max), type(uint256).max >> 1);
+
+ assertEq(stdMath.delta(0, int256(0)), 0);
+ assertEq(stdMath.delta(1337, int256(0)), 1337);
+ assertEq(stdMath.delta(type(int64).max, int256(0)), type(uint64).max >> 1);
+ assertEq(stdMath.delta(type(int128).max, int256(0)), type(uint128).max >> 1);
+ assertEq(stdMath.delta(type(int256).max, int256(0)), type(uint256).max >> 1);
+
+ assertEq(stdMath.delta(-0, int256(0)), 0);
+ assertEq(stdMath.delta(-1337, int256(0)), 1337);
+ assertEq(stdMath.delta(type(int64).min, int256(0)), (type(uint64).max >> 1) + 1);
+ assertEq(stdMath.delta(type(int128).min, int256(0)), (type(uint128).max >> 1) + 1);
+ assertEq(stdMath.delta(type(int256).min, int256(0)), (type(uint256).max >> 1) + 1);
+
+ assertEq(stdMath.delta(int256(0), -0), 0);
+ assertEq(stdMath.delta(int256(0), -1337), 1337);
+ assertEq(stdMath.delta(int256(0), type(int64).min), (type(uint64).max >> 1) + 1);
+ assertEq(stdMath.delta(int256(0), type(int128).min), (type(uint128).max >> 1) + 1);
+ assertEq(stdMath.delta(int256(0), type(int256).min), (type(uint256).max >> 1) + 1);
+
+ assertEq(stdMath.delta(1337, int256(1337)), 0);
+ assertEq(stdMath.delta(type(int256).max, type(int256).max), 0);
+ assertEq(stdMath.delta(type(int256).min, type(int256).min), 0);
+ assertEq(stdMath.delta(type(int256).min, type(int256).max), type(uint256).max);
+ assertEq(stdMath.delta(5000, int256(1250)), 3750);
+ }
+
+ function testFuzz_GetDelta_Int(int256 a, int256 b) external pure {
+ uint256 absA = getAbs(a);
+ uint256 absB = getAbs(b);
+ uint256 absDelta = absA > absB ? absA - absB : absB - absA;
+
+ uint256 manualDelta;
+ if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
+ manualDelta = absDelta;
+ }
+ // (a < 0 && b >= 0) || (a >= 0 && b < 0)
+ else {
+ manualDelta = absA + absB;
+ }
+
+ uint256 delta = stdMath.delta(a, b);
+
+ assertEq(delta, manualDelta);
+ }
+
+ function test_GetPercentDelta_Uint() external {
+ StdMathMock stdMathMock = new StdMathMock();
+
+ assertEq(stdMath.percentDelta(uint256(0), uint256(1337)), 1e18);
+ assertEq(stdMath.percentDelta(uint256(0), type(uint64).max), 1e18);
+ assertEq(stdMath.percentDelta(uint256(0), type(uint128).max), 1e18);
+ assertEq(stdMath.percentDelta(uint256(0), type(uint192).max), 1e18);
+
+ assertEq(stdMath.percentDelta(1337, uint256(1337)), 0);
+ assertEq(stdMath.percentDelta(type(uint192).max, type(uint192).max), 0);
+ assertEq(stdMath.percentDelta(0, uint256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(2500, uint256(2500)), 0);
+ assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18);
+
+ vm.expectRevert(stdError.divisionError);
+ stdMathMock.exposed_percentDelta(uint256(1), 0);
+ }
+
+ function testFuzz_GetPercentDelta_Uint(uint192 a, uint192 b) external pure {
+ vm.assume(b != 0);
+ uint256 manualDelta = a > b ? a - b : b - a;
+
+ uint256 manualPercentDelta = manualDelta * 1e18 / b;
+ uint256 percentDelta = stdMath.percentDelta(a, b);
+
+ assertEq(percentDelta, manualPercentDelta);
+ }
+
+ function test_GetPercentDelta_Int() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdMathMock stdMathMock = new StdMathMock();
+
+ assertEq(stdMath.percentDelta(int256(0), int256(1337)), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), -1337), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int64).min), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int128).min), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int192).min), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int64).max), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int128).max), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int192).max), 1e18);
+
+ assertEq(stdMath.percentDelta(1337, int256(1337)), 0);
+ assertEq(stdMath.percentDelta(type(int192).max, type(int192).max), 0);
+ assertEq(stdMath.percentDelta(type(int192).min, type(int192).min), 0);
+
+ assertEq(stdMath.percentDelta(type(int192).min, type(int192).max), 2e18); // rounds the 1 wei diff down
+ assertEq(stdMath.percentDelta(type(int192).max, type(int192).min), 2e18 - 1); // rounds the 1 wei diff down
+ assertEq(stdMath.percentDelta(0, int256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(2500, int256(2500)), 0);
+ assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18);
+
+ vm.expectRevert(stdError.divisionError);
+ stdMathMock.exposed_percentDelta(int256(1), 0);
+ }
+
+ function testFuzz_GetPercentDelta_Int(int192 a, int192 b) external pure {
+ vm.assume(b != 0);
+ uint256 absA = getAbs(a);
+ uint256 absB = getAbs(b);
+ uint256 absDelta = absA > absB ? absA - absB : absB - absA;
+
+ uint256 manualDelta;
+ if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
+ manualDelta = absDelta;
+ }
+ // (a < 0 && b >= 0) || (a >= 0 && b < 0)
+ else {
+ manualDelta = absA + absB;
+ }
+
+ uint256 manualPercentDelta = manualDelta * 1e18 / absB;
+ uint256 percentDelta = stdMath.percentDelta(a, b);
+
+ assertEq(percentDelta, manualPercentDelta);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ HELPERS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function getAbs(int256 a) private pure returns (uint256) {
+ if (a < 0) {
+ return a == type(int256).min ? uint256(type(int256).max) + 1 : uint256(-a);
+ }
+
+ return uint256(a);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdStorage.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdStorage.t.sol
new file mode 100644
index 000000000..46604f866
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdStorage.t.sol
@@ -0,0 +1,488 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {stdStorage, StdStorage} from "../src/StdStorage.sol";
+import {Test} from "../src/Test.sol";
+
+contract StdStorageTest is Test {
+ using stdStorage for StdStorage;
+
+ StorageTest internal test;
+
+ function setUp() public {
+ test = new StorageTest();
+ }
+
+ function test_StorageHidden() public {
+ assertEq(uint256(keccak256("my.random.var")), stdstore.target(address(test)).sig("hidden()").find());
+ }
+
+ function test_StorageObvious() public {
+ assertEq(uint256(0), stdstore.target(address(test)).sig("exists()").find());
+ }
+
+ function test_StorageExtraSload() public {
+ assertEq(16, stdstore.target(address(test)).sig(test.extra_sload.selector).find());
+ }
+
+ function test_StorageCheckedWriteHidden() public {
+ stdstore.target(address(test)).sig(test.hidden.selector).checked_write(100);
+ assertEq(uint256(test.hidden()), 100);
+ }
+
+ function test_StorageCheckedWriteObvious() public {
+ stdstore.target(address(test)).sig(test.exists.selector).checked_write(100);
+ assertEq(test.exists(), 100);
+ }
+
+ function test_StorageCheckedWriteSignedIntegerHidden() public {
+ stdstore.target(address(test)).sig(test.hidden.selector).checked_write_int(-100);
+ assertEq(int256(uint256(test.hidden())), -100);
+ }
+
+ function test_StorageCheckedWriteSignedIntegerObvious() public {
+ stdstore.target(address(test)).sig(test.tG.selector).checked_write_int(-100);
+ assertEq(test.tG(), -100);
+ }
+
+ function test_StorageMapStructA() public {
+ uint256 slot =
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), 4))), slot);
+ }
+
+ function test_StorageMapStructB() public {
+ uint256 slot =
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), 4))) + 1, slot);
+ }
+
+ function test_StorageDeepMap() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(
+ address(this)
+ ).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(5)))))), slot);
+ }
+
+ function test_StorageCheckedWriteDeepMap() public {
+ stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(address(this))
+ .checked_write(100);
+ assertEq(100, test.deep_map(address(this), address(this)));
+ }
+
+ function test_StorageDeepMapStructA() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
+ .with_key(address(this)).depth(0).find();
+ assertEq(
+ bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0),
+ bytes32(slot)
+ );
+ }
+
+ function test_StorageDeepMapStructB() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
+ .with_key(address(this)).depth(1).find();
+ assertEq(
+ bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1),
+ bytes32(slot)
+ );
+ }
+
+ function test_StorageCheckedWriteDeepMapStructA() public {
+ stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key(
+ address(this)
+ ).depth(0).checked_write(100);
+ (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
+ assertEq(100, a);
+ assertEq(0, b);
+ }
+
+ function test_StorageCheckedWriteDeepMapStructB() public {
+ stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key(
+ address(this)
+ ).depth(1).checked_write(100);
+ (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
+ assertEq(0, a);
+ assertEq(100, b);
+ }
+
+ function test_StorageCheckedWriteMapStructA() public {
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).checked_write(100);
+ (uint256 a, uint256 b) = test.map_struct(address(this));
+ assertEq(a, 100);
+ assertEq(b, 0);
+ }
+
+ function test_StorageCheckedWriteMapStructB() public {
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).checked_write(100);
+ (uint256 a, uint256 b) = test.map_struct(address(this));
+ assertEq(a, 0);
+ assertEq(b, 100);
+ }
+
+ function test_StorageStructA() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(0).find();
+ assertEq(uint256(7), slot);
+ }
+
+ function test_StorageStructB() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(1).find();
+ assertEq(uint256(7) + 1, slot);
+ }
+
+ function test_StorageCheckedWriteStructA() public {
+ stdstore.target(address(test)).sig(test.basic.selector).depth(0).checked_write(100);
+ (uint256 a, uint256 b) = test.basic();
+ assertEq(a, 100);
+ assertEq(b, 1337);
+ }
+
+ function test_StorageCheckedWriteStructB() public {
+ stdstore.target(address(test)).sig(test.basic.selector).depth(1).checked_write(100);
+ (uint256 a, uint256 b) = test.basic();
+ assertEq(a, 1337);
+ assertEq(b, 100);
+ }
+
+ function test_StorageMapAddrFound() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), uint256(1)))), slot);
+ }
+
+ function test_StorageMapAddrRoot() public {
+ (uint256 slot, bytes32 key) =
+ stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).parent();
+ assertEq(address(uint160(uint256(key))), address(this));
+ assertEq(uint256(1), slot);
+ slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).root();
+ assertEq(uint256(1), slot);
+ }
+
+ function test_StorageMapUintFound() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).find();
+ assertEq(uint256(keccak256(abi.encode(100, uint256(2)))), slot);
+ }
+
+ function test_StorageCheckedWriteMapUint() public {
+ stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).checked_write(100);
+ assertEq(100, test.map_uint(100));
+ }
+
+ function test_StorageCheckedWriteMapAddr() public {
+ stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).checked_write(100);
+ assertEq(100, test.map_addr(address(this)));
+ }
+
+ function test_StorageCheckedWriteMapBool() public {
+ stdstore.target(address(test)).sig(test.map_bool.selector).with_key(address(this)).checked_write(true);
+ assertTrue(test.map_bool(address(this)));
+ }
+
+ function testFuzz_StorageCheckedWriteMapPacked(address addr, uint128 value) public {
+ stdstore.enable_packed_slots().target(address(test)).sig(test.read_struct_lower.selector).with_key(addr)
+ .checked_write(value);
+ assertEq(test.read_struct_lower(addr), value);
+
+ stdstore.enable_packed_slots().target(address(test)).sig(test.read_struct_upper.selector).with_key(addr)
+ .checked_write(value);
+ assertEq(test.read_struct_upper(addr), value);
+ }
+
+ function test_StorageCheckedWriteMapPackedFullSuccess() public {
+ uint256 full = test.map_packed(address(1337));
+ // keep upper 128, set lower 128 to 1337
+ full = (full & (uint256((1 << 128) - 1) << 128)) | 1337;
+ stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337))).checked_write(
+ full
+ );
+ assertEq(1337, test.read_struct_lower(address(1337)));
+ }
+
+ function test_RevertStorageConst() public {
+ StorageTestTarget target = new StorageTestTarget(test);
+
+ vm.expectRevert("stdStorage find(StdStorage): No storage use detected for target.");
+ target.expectRevertStorageConst();
+ }
+
+ function testFuzz_StorageNativePack(uint248 val1, uint248 val2, bool boolVal1, bool boolVal2) public {
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tA.selector).checked_write(val1);
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tB.selector).checked_write(boolVal1);
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tC.selector).checked_write(boolVal2);
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tD.selector).checked_write(val2);
+
+ assertEq(test.tA(), val1);
+ assertEq(test.tB(), boolVal1);
+ assertEq(test.tC(), boolVal2);
+ assertEq(test.tD(), val2);
+ }
+
+ function test_StorageReadBytes32() public {
+ bytes32 val = stdstore.target(address(test)).sig(test.tE.selector).read_bytes32();
+ assertEq(val, hex"1337");
+ }
+
+ function test_StorageReadBool_False() public {
+ bool val = stdstore.target(address(test)).sig(test.tB.selector).read_bool();
+ assertEq(val, false);
+ }
+
+ function test_StorageReadBool_True() public {
+ bool val = stdstore.target(address(test)).sig(test.tH.selector).read_bool();
+ assertEq(val, true);
+ }
+
+ function test_RevertIf_ReadingNonBoolValue() public {
+ vm.expectRevert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
+ this.readNonBoolValue();
+ }
+
+ function readNonBoolValue() public {
+ stdstore.target(address(test)).sig(test.tE.selector).read_bool();
+ }
+
+ function test_StorageReadAddress() public {
+ address val = stdstore.target(address(test)).sig(test.tF.selector).read_address();
+ assertEq(val, address(1337));
+ }
+
+ function test_StorageReadUint() public {
+ uint256 val = stdstore.target(address(test)).sig(test.exists.selector).read_uint();
+ assertEq(val, 1);
+ }
+
+ function test_StorageReadInt() public {
+ int256 val = stdstore.target(address(test)).sig(test.tG.selector).read_int();
+ assertEq(val, type(int256).min);
+ }
+
+ function testFuzz_Packed(uint256 val, uint8 elemToGet) public {
+ // This function tries an assortment of packed slots, shifts meaning number of elements
+ // that are packed. Shiftsizes are the size of each element, i.e. 8 means a data type that is 8 bits, 16 == 16 bits, etc.
+ // Combined, these determine how a slot is packed. Making it random is too hard to avoid global rejection limit
+ // and make it performant.
+
+ // change the number of shifts
+ for (uint256 i = 1; i < 5; i++) {
+ uint256 shifts = i;
+
+ elemToGet = uint8(bound(elemToGet, 0, shifts - 1));
+
+ uint256[] memory shiftSizes = new uint256[](shifts);
+ for (uint256 j; j < shifts; j++) {
+ shiftSizes[j] = 8 * (j + 1);
+ }
+
+ test.setRandomPacking(val);
+
+ uint256 leftBits;
+ uint256 rightBits;
+ for (uint256 j; j < shiftSizes.length; j++) {
+ if (j < elemToGet) {
+ leftBits += shiftSizes[j];
+ } else if (elemToGet != j) {
+ rightBits += shiftSizes[j];
+ }
+ }
+
+ // we may have some right bits unaccounted for
+ leftBits += 256 - (leftBits + shiftSizes[elemToGet] + rightBits);
+ // clear left bits, then clear right bits and realign
+ uint256 expectedValToRead = (val << leftBits) >> (leftBits + rightBits);
+
+ uint256 readVal = stdstore.target(address(test)).enable_packed_slots().sig(
+ "getRandomPacked(uint8,uint8[],uint8)"
+ ).with_calldata(abi.encode(shifts, shiftSizes, elemToGet)).read_uint();
+
+ assertEq(readVal, expectedValToRead);
+ }
+ }
+
+ function testFuzz_Packed2(uint256 nvars, uint256 seed) public {
+ // Number of random variables to generate.
+ nvars = bound(nvars, 1, 20);
+
+ // This will decrease as we generate values in the below loop.
+ uint256 bitsRemaining = 256;
+
+ // Generate a random value and size for each variable.
+ uint256[] memory vals = new uint256[](nvars);
+ uint256[] memory sizes = new uint256[](nvars);
+ uint256[] memory offsets = new uint256[](nvars);
+
+ for (uint256 i = 0; i < nvars; i++) {
+ // Generate a random value and size.
+ offsets[i] = i == 0 ? 0 : offsets[i - 1] + sizes[i - 1];
+
+ uint256 nvarsRemaining = nvars - i;
+ uint256 maxVarSize = bitsRemaining - nvarsRemaining + 1;
+ sizes[i] = bound(uint256(keccak256(abi.encodePacked(seed, i + 256))), 1, maxVarSize);
+ bitsRemaining -= sizes[i];
+
+ uint256 maxVal;
+ uint256 varSize = sizes[i];
+ assembly {
+ // mask = (1 << varSize) - 1
+ maxVal := sub(shl(varSize, 1), 1)
+ }
+ vals[i] = bound(uint256(keccak256(abi.encodePacked(seed, i))), 0, maxVal);
+ }
+
+ // Pack all values into the slot.
+ for (uint256 i = 0; i < nvars; i++) {
+ stdstore.enable_packed_slots().target(address(test)).sig("getRandomPacked(uint256,uint256)").with_key(
+ sizes[i]
+ ).with_key(offsets[i]).checked_write(vals[i]);
+ }
+
+ // Verify the read data matches.
+ for (uint256 i = 0; i < nvars; i++) {
+ uint256 readVal = stdstore.enable_packed_slots().target(address(test)).sig(
+ "getRandomPacked(uint256,uint256)"
+ ).with_key(sizes[i]).with_key(offsets[i]).read_uint();
+
+ uint256 retVal = test.getRandomPacked(sizes[i], offsets[i]);
+
+ assertEq(readVal, vals[i]);
+ assertEq(retVal, vals[i]);
+ }
+ }
+
+ function testEdgeCaseArray() public {
+ stdstore.target(address(test)).sig("edgeCaseArray(uint256)").with_key(uint256(0)).checked_write(1);
+ assertEq(test.edgeCaseArray(0), 1);
+ }
+}
+
+contract StorageTestTarget {
+ using stdStorage for StdStorage;
+
+ StdStorage internal stdstore;
+ StorageTest internal test;
+
+ constructor(StorageTest test_) {
+ test = test_;
+ }
+
+ function expectRevertStorageConst() public {
+ stdstore.target(address(test)).sig("const()").find();
+ }
+}
+
+contract StorageTest {
+ uint256 public exists = 1;
+ mapping(address => uint256) public map_addr;
+ mapping(uint256 => uint256) public map_uint;
+ mapping(address => uint256) public map_packed;
+ mapping(address => UnpackedStruct) public map_struct;
+ mapping(address => mapping(address => uint256)) public deep_map;
+ mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
+ UnpackedStruct public basic;
+
+ uint248 public tA;
+ bool public tB;
+
+ bool public tC = false;
+ uint248 public tD = 1;
+
+ struct UnpackedStruct {
+ uint256 a;
+ uint256 b;
+ }
+
+ mapping(address => bool) public map_bool;
+
+ bytes32 public tE = hex"1337";
+ address public tF = address(1337);
+ int256 public tG = type(int256).min;
+ bool public tH = true;
+ bytes32 private tI = ~bytes32(hex"1337");
+
+ uint256 randomPacking;
+
+ // Array with length matching values of elements.
+ uint256[] public edgeCaseArray = [3, 3, 3];
+
+ constructor() {
+ basic = UnpackedStruct({a: 1337, b: 1337});
+
+ uint256 two = (1 << 128) | 1;
+ map_packed[msg.sender] = two;
+ map_packed[address(uint160(1337))] = 1 << 128;
+ }
+
+ function read_struct_upper(address who) public view returns (uint256) {
+ return map_packed[who] >> 128;
+ }
+
+ function read_struct_lower(address who) public view returns (uint256) {
+ return map_packed[who] & ((1 << 128) - 1);
+ }
+
+ function hidden() public view returns (bytes32 t) {
+ bytes32 slot = keccak256("my.random.var");
+ /// @solidity memory-safe-assembly
+ assembly {
+ t := sload(slot)
+ }
+ }
+
+ function const() public pure returns (bytes32 t) {
+ t = bytes32(hex"1337");
+ }
+
+ function extra_sload() public view returns (bytes32 t) {
+ // trigger read on slot `tE`, and make a staticcall to make sure compiler doesn't optimize this SLOAD away
+ assembly {
+ pop(staticcall(gas(), sload(tE.slot), 0, 0, 0, 0))
+ }
+ t = tI;
+ }
+
+ function setRandomPacking(uint256 val) public {
+ randomPacking = val;
+ }
+
+ function _getMask(uint256 size) internal pure returns (uint256 mask) {
+ assembly {
+ // mask = (1 << size) - 1
+ mask := sub(shl(size, 1), 1)
+ }
+ }
+
+ function setRandomPacking(uint256 val, uint256 size, uint256 offset) public {
+ // Generate mask based on the size of the value
+ uint256 mask = _getMask(size);
+ // Zero out all bits for the word we're about to set
+ uint256 cleanedWord = randomPacking & ~(mask << offset);
+ // Place val in the correct spot of the cleaned word
+ randomPacking = cleanedWord | val << offset;
+ }
+
+ function getRandomPacked(uint256 size, uint256 offset) public view returns (uint256) {
+ // Generate mask based on the size of the value
+ uint256 mask = _getMask(size);
+ // Shift to place the bits in the correct position, and use mask to zero out remaining bits
+ return (randomPacking >> offset) & mask;
+ }
+
+ function getRandomPacked(uint8 shifts, uint8[] memory shiftSizes, uint8 elem) public view returns (uint256) {
+ require(elem < shifts, "!elem");
+ uint256 leftBits;
+ uint256 rightBits;
+
+ for (uint256 i; i < shiftSizes.length; i++) {
+ if (i < elem) {
+ leftBits += shiftSizes[i];
+ } else if (elem != i) {
+ rightBits += shiftSizes[i];
+ }
+ }
+
+ // we may have some right bits unaccounted for
+ leftBits += 256 - (leftBits + shiftSizes[elem] + rightBits);
+
+ // clear left bits, then clear right bits and realign
+ return (randomPacking << leftBits) >> (leftBits + rightBits);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdStyle.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdStyle.t.sol
new file mode 100644
index 000000000..974e756fe
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdStyle.t.sol
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, console2, StdStyle} from "../src/Test.sol";
+
+contract StdStyleTest is Test {
+ function test_StyleColor() public pure {
+ console2.log(StdStyle.red("StdStyle.red String Test"));
+ console2.log(StdStyle.red(uint256(10e18)));
+ console2.log(StdStyle.red(int256(-10e18)));
+ console2.log(StdStyle.red(true));
+ console2.log(StdStyle.red(address(0)));
+ console2.log(StdStyle.redBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.redBytes32("StdStyle.redBytes32"));
+ console2.log(StdStyle.green("StdStyle.green String Test"));
+ console2.log(StdStyle.green(uint256(10e18)));
+ console2.log(StdStyle.green(int256(-10e18)));
+ console2.log(StdStyle.green(true));
+ console2.log(StdStyle.green(address(0)));
+ console2.log(StdStyle.greenBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.greenBytes32("StdStyle.greenBytes32"));
+ console2.log(StdStyle.yellow("StdStyle.yellow String Test"));
+ console2.log(StdStyle.yellow(uint256(10e18)));
+ console2.log(StdStyle.yellow(int256(-10e18)));
+ console2.log(StdStyle.yellow(true));
+ console2.log(StdStyle.yellow(address(0)));
+ console2.log(StdStyle.yellowBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.yellowBytes32("StdStyle.yellowBytes32"));
+ console2.log(StdStyle.blue("StdStyle.blue String Test"));
+ console2.log(StdStyle.blue(uint256(10e18)));
+ console2.log(StdStyle.blue(int256(-10e18)));
+ console2.log(StdStyle.blue(true));
+ console2.log(StdStyle.blue(address(0)));
+ console2.log(StdStyle.blueBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.blueBytes32("StdStyle.blueBytes32"));
+ console2.log(StdStyle.magenta("StdStyle.magenta String Test"));
+ console2.log(StdStyle.magenta(uint256(10e18)));
+ console2.log(StdStyle.magenta(int256(-10e18)));
+ console2.log(StdStyle.magenta(true));
+ console2.log(StdStyle.magenta(address(0)));
+ console2.log(StdStyle.magentaBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.magentaBytes32("StdStyle.magentaBytes32"));
+ console2.log(StdStyle.cyan("StdStyle.cyan String Test"));
+ console2.log(StdStyle.cyan(uint256(10e18)));
+ console2.log(StdStyle.cyan(int256(-10e18)));
+ console2.log(StdStyle.cyan(true));
+ console2.log(StdStyle.cyan(address(0)));
+ console2.log(StdStyle.cyanBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.cyanBytes32("StdStyle.cyanBytes32"));
+ }
+
+ function test_StyleFontWeight() public pure {
+ console2.log(StdStyle.bold("StdStyle.bold String Test"));
+ console2.log(StdStyle.bold(uint256(10e18)));
+ console2.log(StdStyle.bold(int256(-10e18)));
+ console2.log(StdStyle.bold(address(0)));
+ console2.log(StdStyle.bold(true));
+ console2.log(StdStyle.boldBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.boldBytes32("StdStyle.boldBytes32"));
+ console2.log(StdStyle.dim("StdStyle.dim String Test"));
+ console2.log(StdStyle.dim(uint256(10e18)));
+ console2.log(StdStyle.dim(int256(-10e18)));
+ console2.log(StdStyle.dim(address(0)));
+ console2.log(StdStyle.dim(true));
+ console2.log(StdStyle.dimBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.dimBytes32("StdStyle.dimBytes32"));
+ console2.log(StdStyle.italic("StdStyle.italic String Test"));
+ console2.log(StdStyle.italic(uint256(10e18)));
+ console2.log(StdStyle.italic(int256(-10e18)));
+ console2.log(StdStyle.italic(address(0)));
+ console2.log(StdStyle.italic(true));
+ console2.log(StdStyle.italicBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.italicBytes32("StdStyle.italicBytes32"));
+ console2.log(StdStyle.underline("StdStyle.underline String Test"));
+ console2.log(StdStyle.underline(uint256(10e18)));
+ console2.log(StdStyle.underline(int256(-10e18)));
+ console2.log(StdStyle.underline(address(0)));
+ console2.log(StdStyle.underline(true));
+ console2.log(StdStyle.underlineBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.underlineBytes32("StdStyle.underlineBytes32"));
+ console2.log(StdStyle.inverse("StdStyle.inverse String Test"));
+ console2.log(StdStyle.inverse(uint256(10e18)));
+ console2.log(StdStyle.inverse(int256(-10e18)));
+ console2.log(StdStyle.inverse(address(0)));
+ console2.log(StdStyle.inverse(true));
+ console2.log(StdStyle.inverseBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.inverseBytes32("StdStyle.inverseBytes32"));
+ }
+
+ function test_StyleCombined() public pure {
+ console2.log(StdStyle.red(StdStyle.bold("Red Bold String Test")));
+ console2.log(StdStyle.green(StdStyle.dim(uint256(10e18))));
+ console2.log(StdStyle.yellow(StdStyle.italic(int256(-10e18))));
+ console2.log(StdStyle.blue(StdStyle.underline(address(0))));
+ console2.log(StdStyle.magenta(StdStyle.inverse(true)));
+ }
+
+ function test_StyleCustom() public pure {
+ console2.log(h1("Custom Style 1"));
+ console2.log(h2("Custom Style 2"));
+ }
+
+ function h1(string memory a) private pure returns (string memory) {
+ return StdStyle.cyan(StdStyle.inverse(StdStyle.bold(a)));
+ }
+
+ function h2(string memory a) private pure returns (string memory) {
+ return StdStyle.magenta(StdStyle.bold(StdStyle.underline(a)));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdToml.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdToml.t.sol
new file mode 100644
index 000000000..5a45f4f5c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdToml.t.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, stdToml} from "../src/Test.sol";
+
+contract StdTomlTest is Test {
+ using stdToml for string;
+
+ string root;
+ string path;
+
+ function setUp() public {
+ root = vm.projectRoot();
+ path = string.concat(root, "/test/fixtures/test.toml");
+ }
+
+ struct SimpleToml {
+ uint256 a;
+ string b;
+ }
+
+ struct NestedToml {
+ uint256 a;
+ string b;
+ SimpleToml c;
+ }
+
+ function test_readToml() public view {
+ string memory json = vm.readFile(path);
+ assertEq(json.readUint(".a"), 123);
+ }
+
+ function test_writeToml() public {
+ string memory json = "json";
+ json.serialize("a", uint256(123));
+ string memory semiFinal = json.serialize("b", string("test"));
+ string memory finalJson = json.serialize("c", semiFinal);
+ finalJson.write(path);
+
+ string memory toml = vm.readFile(path);
+ bytes memory data = toml.parseRaw("$");
+ NestedToml memory decodedData = abi.decode(data, (NestedToml));
+
+ assertEq(decodedData.a, 123);
+ assertEq(decodedData.b, "test");
+ assertEq(decodedData.c.a, 123);
+ assertEq(decodedData.c.b, "test");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/StdUtils.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/StdUtils.t.sol
new file mode 100644
index 000000000..aee801b2c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/StdUtils.t.sol
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, StdUtils} from "../src/Test.sol";
+
+contract StdUtilsMock is StdUtils {
+ // We deploy a mock version so we can properly test expected reverts.
+ function exposed_getTokenBalances(address token, address[] memory addresses)
+ external
+ returns (uint256[] memory balances)
+ {
+ return getTokenBalances(token, addresses);
+ }
+
+ function exposed_bound(int256 num, int256 min, int256 max) external pure returns (int256) {
+ return bound(num, min, max);
+ }
+
+ function exposed_bound(uint256 num, uint256 min, uint256 max) external pure returns (uint256) {
+ return bound(num, min, max);
+ }
+
+ function exposed_bytesToUint(bytes memory b) external pure returns (uint256) {
+ return bytesToUint(b);
+ }
+}
+
+contract StdUtilsTest is Test {
+ /*//////////////////////////////////////////////////////////////////////////
+ BOUND UINT
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_Bound() public pure {
+ assertEq(bound(uint256(5), 0, 4), 0);
+ assertEq(bound(uint256(0), 69, 69), 69);
+ assertEq(bound(uint256(0), 68, 69), 68);
+ assertEq(bound(uint256(10), 150, 190), 174);
+ assertEq(bound(uint256(300), 2800, 3200), 3107);
+ assertEq(bound(uint256(9999), 1337, 6666), 4669);
+ }
+
+ function test_Bound_WithinRange() public pure {
+ assertEq(bound(uint256(51), 50, 150), 51);
+ assertEq(bound(uint256(51), 50, 150), bound(bound(uint256(51), 50, 150), 50, 150));
+ assertEq(bound(uint256(149), 50, 150), 149);
+ assertEq(bound(uint256(149), 50, 150), bound(bound(uint256(149), 50, 150), 50, 150));
+ }
+
+ function test_Bound_EdgeCoverage() public pure {
+ assertEq(bound(uint256(0), 50, 150), 50);
+ assertEq(bound(uint256(1), 50, 150), 51);
+ assertEq(bound(uint256(2), 50, 150), 52);
+ assertEq(bound(uint256(3), 50, 150), 53);
+ assertEq(bound(type(uint256).max, 50, 150), 150);
+ assertEq(bound(type(uint256).max - 1, 50, 150), 149);
+ assertEq(bound(type(uint256).max - 2, 50, 150), 148);
+ assertEq(bound(type(uint256).max - 3, 50, 150), 147);
+ }
+
+ function testFuzz_Bound_DistributionIsEven(uint256 min, uint256 size) public pure {
+ size = size % 100 + 1;
+ min = bound(min, UINT256_MAX / 2, UINT256_MAX / 2 + size);
+ uint256 max = min + size - 1;
+ uint256 result;
+
+ for (uint256 i = 1; i <= size * 4; ++i) {
+ // x > max
+ result = bound(max + i, min, max);
+ assertEq(result, min + (i - 1) % size);
+ // x < min
+ result = bound(min - i, min, max);
+ assertEq(result, max - (i - 1) % size);
+ }
+ }
+
+ function testFuzz_Bound(uint256 num, uint256 min, uint256 max) public pure {
+ if (min > max) (min, max) = (max, min);
+
+ uint256 result = bound(num, min, max);
+
+ assertGe(result, min);
+ assertLe(result, max);
+ assertEq(result, bound(result, min, max));
+ if (num >= min && num <= max) assertEq(result, num);
+ }
+
+ function test_BoundUint256Max() public pure {
+ assertEq(bound(0, type(uint256).max - 1, type(uint256).max), type(uint256).max - 1);
+ assertEq(bound(1, type(uint256).max - 1, type(uint256).max), type(uint256).max);
+ }
+
+ function test_RevertIf_BoundMaxLessThanMin() public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
+ stdUtils.exposed_bound(uint256(5), 100, 10);
+ }
+
+ function testFuzz_RevertIf_BoundMaxLessThanMin(uint256 num, uint256 min, uint256 max) public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.assume(min > max);
+ vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
+ stdUtils.exposed_bound(num, min, max);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ BOUND INT
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_BoundInt() public pure {
+ assertEq(bound(-3, 0, 4), 2);
+ assertEq(bound(0, -69, -69), -69);
+ assertEq(bound(0, -69, -68), -68);
+ assertEq(bound(-10, 150, 190), 154);
+ assertEq(bound(-300, 2800, 3200), 2908);
+ assertEq(bound(9999, -1337, 6666), 1995);
+ }
+
+ function test_BoundInt_WithinRange() public pure {
+ assertEq(bound(51, -50, 150), 51);
+ assertEq(bound(51, -50, 150), bound(bound(51, -50, 150), -50, 150));
+ assertEq(bound(149, -50, 150), 149);
+ assertEq(bound(149, -50, 150), bound(bound(149, -50, 150), -50, 150));
+ }
+
+ function test_BoundInt_EdgeCoverage() public pure {
+ assertEq(bound(type(int256).min, -50, 150), -50);
+ assertEq(bound(type(int256).min + 1, -50, 150), -49);
+ assertEq(bound(type(int256).min + 2, -50, 150), -48);
+ assertEq(bound(type(int256).min + 3, -50, 150), -47);
+ assertEq(bound(type(int256).min, 10, 150), 10);
+ assertEq(bound(type(int256).min + 1, 10, 150), 11);
+ assertEq(bound(type(int256).min + 2, 10, 150), 12);
+ assertEq(bound(type(int256).min + 3, 10, 150), 13);
+
+ assertEq(bound(type(int256).max, -50, 150), 150);
+ assertEq(bound(type(int256).max - 1, -50, 150), 149);
+ assertEq(bound(type(int256).max - 2, -50, 150), 148);
+ assertEq(bound(type(int256).max - 3, -50, 150), 147);
+ assertEq(bound(type(int256).max, -50, -10), -10);
+ assertEq(bound(type(int256).max - 1, -50, -10), -11);
+ assertEq(bound(type(int256).max - 2, -50, -10), -12);
+ assertEq(bound(type(int256).max - 3, -50, -10), -13);
+ }
+
+ function testFuzz_BoundInt_DistributionIsEven(int256 min, uint256 size) public pure {
+ size = size % 100 + 1;
+ min = bound(min, -int256(size / 2), int256(size - size / 2));
+ int256 max = min + int256(size) - 1;
+ int256 result;
+
+ for (uint256 i = 1; i <= size * 4; ++i) {
+ // x > max
+ result = bound(max + int256(i), min, max);
+ assertEq(result, min + int256((i - 1) % size));
+ // x < min
+ result = bound(min - int256(i), min, max);
+ assertEq(result, max - int256((i - 1) % size));
+ }
+ }
+
+ function testFuzz_BoundInt(int256 num, int256 min, int256 max) public pure {
+ if (min > max) (min, max) = (max, min);
+
+ int256 result = bound(num, min, max);
+
+ assertGe(result, min);
+ assertLe(result, max);
+ assertEq(result, bound(result, min, max));
+ if (num >= min && num <= max) assertEq(result, num);
+ }
+
+ function test_BoundIntInt256Max() public pure {
+ assertEq(bound(0, type(int256).max - 1, type(int256).max), type(int256).max - 1);
+ assertEq(bound(1, type(int256).max - 1, type(int256).max), type(int256).max);
+ }
+
+ function test_BoundIntInt256Min() public pure {
+ assertEq(bound(0, type(int256).min, type(int256).min + 1), type(int256).min);
+ assertEq(bound(1, type(int256).min, type(int256).min + 1), type(int256).min + 1);
+ }
+
+ function test_RevertIf_BoundIntMaxLessThanMin() public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
+ stdUtils.exposed_bound(-5, 100, 10);
+ }
+
+ function testFuzz_RevertIf_BoundIntMaxLessThanMin(int256 num, int256 min, int256 max) public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.assume(min > max);
+ vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
+ stdUtils.exposed_bound(num, min, max);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ BOUND PRIVATE KEY
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_BoundPrivateKey() public pure {
+ assertEq(boundPrivateKey(0), 1);
+ assertEq(boundPrivateKey(1), 1);
+ assertEq(boundPrivateKey(300), 300);
+ assertEq(boundPrivateKey(9999), 9999);
+ assertEq(boundPrivateKey(SECP256K1_ORDER - 1), SECP256K1_ORDER - 1);
+ assertEq(boundPrivateKey(SECP256K1_ORDER), 1);
+ assertEq(boundPrivateKey(SECP256K1_ORDER + 1), 2);
+ assertEq(boundPrivateKey(UINT256_MAX), UINT256_MAX & SECP256K1_ORDER - 1); // x&y is equivalent to x-x%y
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ BYTES TO UINT
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_BytesToUint() external pure {
+ bytes memory maxUint = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ bytes memory two = hex"02";
+ bytes memory millionEther = hex"d3c21bcecceda1000000";
+
+ assertEq(bytesToUint(maxUint), type(uint256).max);
+ assertEq(bytesToUint(two), 2);
+ assertEq(bytesToUint(millionEther), 1_000_000 ether);
+ }
+
+ function test_RevertIf_BytesLengthExceeds32() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ bytes memory thirty3Bytes = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ vm.expectRevert("StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
+ stdUtils.exposed_bytesToUint(thirty3Bytes);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ COMPUTE CREATE ADDRESS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_ComputeCreateAddress() external pure {
+ address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
+ uint256 nonce = 14;
+ address createAddress = computeCreateAddress(deployer, nonce);
+ assertEq(createAddress, 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ COMPUTE CREATE2 ADDRESS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_ComputeCreate2Address() external pure {
+ bytes32 salt = bytes32(uint256(31415));
+ bytes32 initcodeHash = keccak256(abi.encode(0x6080));
+ address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
+ address create2Address = computeCreate2Address(salt, initcodeHash, deployer);
+ assertEq(create2Address, 0xB147a5d25748fda14b463EB04B111027C290f4d3);
+ }
+
+ function test_ComputeCreate2AddressWithDefaultDeployer() external pure {
+ bytes32 salt = 0xc290c670fde54e5ef686f9132cbc8711e76a98f0333a438a92daa442c71403c0;
+ bytes32 initcodeHash = hashInitCode(hex"6080", "");
+ assertEq(initcodeHash, 0x1a578b7a4b0b5755db6d121b4118d4bc68fe170dca840c59bc922f14175a76b0);
+ address create2Address = computeCreate2Address(salt, initcodeHash);
+ assertEq(create2Address, 0xc0ffEe2198a06235aAbFffe5Db0CacF1717f5Ac6);
+ }
+}
+
+contract StdUtilsForkTest is Test {
+ /*//////////////////////////////////////////////////////////////////////////
+ GET TOKEN BALANCES
+ //////////////////////////////////////////////////////////////////////////*/
+
+ address internal SHIB = 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE;
+ address internal SHIB_HOLDER_0 = 0x855F5981e831D83e6A4b4EBFCAdAa68D92333170;
+ address internal SHIB_HOLDER_1 = 0x8F509A90c2e47779cA408Fe00d7A72e359229AdA;
+ address internal SHIB_HOLDER_2 = 0x0e3bbc0D04fF62211F71f3e4C45d82ad76224385;
+
+ address internal USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
+ address internal USDC_HOLDER_0 = 0xDa9CE944a37d218c3302F6B82a094844C6ECEb17;
+ address internal USDC_HOLDER_1 = 0x3e67F4721E6d1c41a015f645eFa37BEd854fcf52;
+
+ function setUp() public {
+ // All tests of the `getTokenBalances` method are fork tests using live contracts.
+ vm.createSelectFork({urlOrAlias: "mainnet", blockNumber: 16_428_900});
+ }
+
+ function test_RevertIf_CannotGetTokenBalances_NonTokenContract() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ // The UniswapV2Factory contract has neither a `balanceOf` function nor a fallback function,
+ // so the `balanceOf` call should revert.
+ address token = address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);
+ address[] memory addresses = new address[](1);
+ addresses[0] = USDC_HOLDER_0;
+
+ vm.expectRevert("Multicall3: call failed");
+ stdUtils.exposed_getTokenBalances(token, addresses);
+ }
+
+ function test_RevertIf_CannotGetTokenBalances_EOA() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ address eoa = vm.addr({privateKey: 1});
+ address[] memory addresses = new address[](1);
+ addresses[0] = USDC_HOLDER_0;
+ vm.expectRevert("StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
+ stdUtils.exposed_getTokenBalances(eoa, addresses);
+ }
+
+ function test_GetTokenBalances_Empty() external {
+ address[] memory addresses = new address[](0);
+ uint256[] memory balances = getTokenBalances(USDC, addresses);
+ assertEq(balances.length, 0);
+ }
+
+ function test_GetTokenBalances_USDC() external {
+ address[] memory addresses = new address[](2);
+ addresses[0] = USDC_HOLDER_0;
+ addresses[1] = USDC_HOLDER_1;
+ uint256[] memory balances = getTokenBalances(USDC, addresses);
+ assertEq(balances[0], 159_000_000_000_000);
+ assertEq(balances[1], 131_350_000_000_000);
+ }
+
+ function test_GetTokenBalances_SHIB() external {
+ address[] memory addresses = new address[](3);
+ addresses[0] = SHIB_HOLDER_0;
+ addresses[1] = SHIB_HOLDER_1;
+ addresses[2] = SHIB_HOLDER_2;
+ uint256[] memory balances = getTokenBalances(SHIB, addresses);
+ assertEq(balances[0], 3_323_256_285_484.42e18);
+ assertEq(balances[1], 1_271_702_771_149.99999928e18);
+ assertEq(balances[2], 606_357_106_247e18);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/Vm.t.sol b/lib/signals-implicit-mode/lib/forge-std/test/Vm.t.sol
new file mode 100644
index 000000000..1b99e3db1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/Vm.t.sol
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.0 <0.9.0;
+
+import {Test} from "../src/Test.sol";
+import {Vm, VmSafe} from "../src/Vm.sol";
+
+// These tests ensure that functions are never accidentally removed from a Vm interface, or
+// inadvertently moved between Vm and VmSafe. These tests must be updated each time a function is
+// added to or removed from Vm or VmSafe.
+contract VmTest is Test {
+ function test_VmInterfaceId() public pure {
+ assertEq(type(Vm).interfaceId, bytes4(0xe835828d), "Vm");
+ }
+
+ function test_VmSafeInterfaceId() public pure {
+ assertEq(type(VmSafe).interfaceId, bytes4(0xe02727c3), "VmSafe");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationScript.sol b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationScript.sol
new file mode 100644
index 000000000..d3d88a0b5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationScript.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {Script} from "../../src/Script.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationScript is Script {}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationScriptBase.sol b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationScriptBase.sol
new file mode 100644
index 000000000..65b5bedbe
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationScriptBase.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {ScriptBase} from "../../src/Script.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationScriptBase is ScriptBase {}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationTest.sol b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationTest.sol
new file mode 100644
index 000000000..2a9dec57f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationTest.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {Test} from "../../src/Test.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationTest is Test {}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationTestBase.sol b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationTestBase.sol
new file mode 100644
index 000000000..32b3fc5be
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/compilation/CompilationTestBase.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {TestBase} from "../../src/Test.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationTestBase is TestBase {}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/fixtures/broadcast.log.json b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/broadcast.log.json
new file mode 100644
index 000000000..0a0200bca
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/broadcast.log.json
@@ -0,0 +1,187 @@
+{
+ "transactions": [
+ {
+ "hash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f",
+ "type": "CALL",
+ "contractName": "Test",
+ "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "function": "multiple_arguments(uint256,address,uint256[]):(uint256)",
+ "arguments": ["1", "0000000000000000000000000000000000001337", "[3,4]"],
+ "tx": {
+ "type": "0x02",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "gas": "0x73b9",
+ "value": "0x0",
+ "data": "0x23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004",
+ "nonce": "0x3",
+ "accessList": []
+ }
+ },
+ {
+ "hash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298",
+ "type": "CALL",
+ "contractName": "Test",
+ "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "function": "inc():(uint256)",
+ "arguments": [],
+ "tx": {
+ "type": "0x02",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "gas": "0xdcb2",
+ "value": "0x0",
+ "data": "0x371303c0",
+ "nonce": "0x4",
+ "accessList": []
+ }
+ },
+ {
+ "hash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
+ "type": "CALL",
+ "contractName": "Test",
+ "contractAddress": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "function": "t(uint256):(uint256)",
+ "arguments": ["1"],
+ "tx": {
+ "type": "0x02",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "gas": "0x8599",
+ "value": "0x0",
+ "data": "0xafe29f710000000000000000000000000000000000000000000000000000000000000001",
+ "nonce": "0x5",
+ "accessList": []
+ }
+ }
+ ],
+ "receipts": [
+ {
+ "transactionHash": "0x481dc86e40bba90403c76f8e144aa9ff04c1da2164299d0298573835f0991181",
+ "transactionIndex": "0x0",
+ "blockHash": "0xef0730448490304e5403be0fa8f8ce64f118e9adcca60c07a2ae1ab921d748af",
+ "blockNumber": "0x1",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": null,
+ "cumulativeGasUsed": "0x13f3a",
+ "gasUsed": "0x13f3a",
+ "contractAddress": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0x6a187183545b8a9e7f1790e847139379bf5622baff2cb43acf3f5c79470af782",
+ "transactionIndex": "0x0",
+ "blockHash": "0xf3acb96a90071640c2a8c067ae4e16aad87e634ea8d8bbbb5b352fba86ba0148",
+ "blockNumber": "0x2",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": null,
+ "cumulativeGasUsed": "0x45d80",
+ "gasUsed": "0x45d80",
+ "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0x064ad173b4867bdef2fb60060bbdaf01735fbf10414541ea857772974e74ea9d",
+ "transactionIndex": "0x0",
+ "blockHash": "0x8373d02109d3ee06a0225f23da4c161c656ccc48fe0fcee931d325508ae73e58",
+ "blockNumber": "0x3",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c",
+ "cumulativeGasUsed": "0x45feb",
+ "gasUsed": "0x45feb",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f",
+ "transactionIndex": "0x0",
+ "blockHash": "0x16712fae5c0e18f75045f84363fb6b4d9a9fe25e660c4ce286833a533c97f629",
+ "blockNumber": "0x4",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "cumulativeGasUsed": "0x5905",
+ "gasUsed": "0x5905",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298",
+ "transactionIndex": "0x0",
+ "blockHash": "0x156b88c3eb9a1244ba00a1834f3f70de735b39e3e59006dd03af4fe7d5480c11",
+ "blockNumber": "0x5",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "cumulativeGasUsed": "0xa9c4",
+ "gasUsed": "0xa9c4",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
+ "transactionIndex": "0x0",
+ "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb",
+ "blockNumber": "0x6",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "cumulativeGasUsed": "0x66c5",
+ "gasUsed": "0x66c5",
+ "contractAddress": null,
+ "logs": [
+ {
+ "address": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "topics": [
+ "0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000046865726500000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb",
+ "blockNumber": "0x6",
+ "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
+ "transactionIndex": "0x1",
+ "logIndex": "0x0",
+ "transactionLogIndex": "0x0",
+ "removed": false
+ }
+ ],
+ "status": "0x1",
+ "logsBloom": "0x00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0x11fbb10230c168ca1e36a7e5c69a6dbcd04fd9e64ede39d10a83e36ee8065c16",
+ "transactionIndex": "0x0",
+ "blockHash": "0xf1e0ed2eda4e923626ec74621006ed50b3fc27580dc7b4cf68a07ca77420e29c",
+ "blockNumber": "0x7",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x0000000000000000000000000000000000001337",
+ "cumulativeGasUsed": "0x5208",
+ "gasUsed": "0x5208",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ }
+ ],
+ "libraries": [
+ "src/Broadcast.t.sol:F:0x5fbdb2315678afecb367f032d93f642f64180aa3"
+ ],
+ "pending": [],
+ "path": "broadcast/Broadcast.t.sol/31337/run-latest.json",
+ "returns": {},
+ "timestamp": 1655140035
+}
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/fixtures/config.toml b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/config.toml
new file mode 100644
index 000000000..e6dcccca5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/config.toml
@@ -0,0 +1,81 @@
+# ------------------------------------------------
+# EXAMPLE DEPLOYMENT CONFIG
+# ------------------------------------------------
+
+# -- MAINNET -------------------------------------
+
+[mainnet]
+endpoint_url = "${MAINNET_RPC}"
+
+[mainnet.bool]
+is_live = true
+bool_array = [true, false]
+
+[mainnet.address]
+weth = "${WETH_MAINNET}"
+deps = [
+ "0x0000000000000000000000000000000000000000",
+ "0x1111111111111111111111111111111111111111",
+]
+
+[mainnet.uint]
+number = 1234
+number_array = [5678, 9999]
+
+[mainnet.int]
+signed_number = -1234
+signed_number_array = [-5678, 9999]
+
+[mainnet.bytes32]
+word = "0x00000000000000000000000000000000000000000000000000000000000004d2" # 1234
+word_array = [
+ "0x000000000000000000000000000000000000000000000000000000000000162e", # 5678
+ "0x000000000000000000000000000000000000000000000000000000000000270f", # 9999
+]
+
+[mainnet.bytes]
+b = "0xabcd"
+b_array = ["0xdead", "0xbeef"]
+
+[mainnet.string]
+str = "foo"
+str_array = ["bar", "baz"]
+
+# -- OPTIMISM ------------------------------------
+
+[optimism]
+endpoint_url = "${OPTIMISM_RPC}"
+
+[optimism.bool]
+is_live = false
+bool_array = [false, true]
+
+[optimism.address]
+weth = "${WETH_OPTIMISM}"
+deps = [
+ "0x2222222222222222222222222222222222222222",
+ "0x3333333333333333333333333333333333333333",
+]
+
+[optimism.uint]
+number = 9999
+number_array = [1234, 5678]
+
+[optimism.int]
+signed_number = 9999
+signed_number_array = [-1234, -5678]
+
+[optimism.bytes32]
+word = "0x000000000000000000000000000000000000000000000000000000000000270f" # 9999
+word_array = [
+ "0x00000000000000000000000000000000000000000000000000000000000004d2", # 1234
+ "0x000000000000000000000000000000000000000000000000000000000000162e", # 5678
+]
+
+[optimism.bytes]
+b = "0xdcba"
+b_array = ["0xc0ffee", "0xbabe"]
+
+[optimism.string]
+str = "alice"
+str_array = ["bob", "charlie"]
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/fixtures/test.json b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/test.json
new file mode 100644
index 000000000..caebf6d96
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/test.json
@@ -0,0 +1,8 @@
+{
+ "a": 123,
+ "b": "test",
+ "c": {
+ "a": 123,
+ "b": "test"
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/forge-std/test/fixtures/test.toml b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/test.toml
new file mode 100644
index 000000000..60692bc75
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/forge-std/test/fixtures/test.toml
@@ -0,0 +1,6 @@
+a = 123
+b = "test"
+
+[c]
+a = 123
+b = "test"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/.env.sample b/lib/signals-implicit-mode/lib/sequence-v3/.env.sample
new file mode 100644
index 000000000..323d6deba
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/.env.sample
@@ -0,0 +1,7 @@
+PRIVATE_KEY=
+ERC4337_ENTRY_POINT_V7=0x0000000071727De22E5E9d8BAf0edAc6f37da032
+
+SEQ_SDK_RPC_URL_PREFIX="http://localhost:"
+SEQ_SDK_RPC_URL_SUFFIX="/rpc"
+SEQ_SDK_RPC_MIN_PORT=9999
+SEQ_SDK_RPC_MAX_PORT=9999
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/.github/workflows/tests.yml b/lib/signals-implicit-mode/lib/sequence-v3/.github/workflows/tests.yml
new file mode 100644
index 000000000..8c2a4a90e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/.github/workflows/tests.yml
@@ -0,0 +1,148 @@
+name: Tests
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.sha }}
+ cancel-in-progress: true
+
+on:
+ workflow_dispatch:
+ inputs:
+ sdk_type:
+ description: 'Type of test to run: go or typescript'
+ required: true
+ type: choice
+ options:
+ - go
+ - typescript
+ commit_hash:
+ description: 'Commit hash of the SDK to test against'
+ required: false
+ type: string
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: Go SDK
+ sdk_type: go
+ repo_name: go-sequence
+ clone_url: https://github.com/0xsequence/go-sequence.git
+ repo_url: https://github.com/0xsequence/go-sequence.git
+ ssh_url: git@github.com:0xsequence/go-sequence.git
+ default_branch: v3-core
+ setup_tool: go
+ setup_version: '1.23'
+ build_cmd: go mod tidy && go build -o sequence-server ./cmd/sequence
+ server_cmd: ./sequence-server server &
+ - name: Typescript SDK
+ sdk_type: typescript
+ repo_name: sequence.js
+ clone_url: https://github.com/0xsequence/sequence.js.git
+ repo_url: https://github.com/0xsequence/sequence.js.git
+ ssh_url: git@github.com:0xsequence/sequence.js.git
+ default_branch: master
+ setup_tool: node
+ setup_version: '20'
+ build_cmd: npm install -g pnpm && pnpm install && pnpm run build:packages
+ server_cmd: pnpm dev:server &
+
+ steps:
+ - name: Determine SDK Git Commit
+ id: determine_commit
+ run: |
+ if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ -n "${{ github.event.inputs.commit_hash }}" ]; then
+ echo "commit=${{ github.event.inputs.commit_hash }}" >> $GITHUB_OUTPUT
+ else
+ echo "commit=${{ matrix.default_branch }}" >> $GITHUB_OUTPUT
+ fi
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Clone SDK Repo
+ run: |
+ git clone ${{ matrix.clone_url }} sdk-repo
+ cd sdk-repo
+ git checkout ${{ steps.determine_commit.outputs.commit }}
+ cd ..
+ - name: Set Up Go Environment
+ if: ${{ matrix.setup_tool == 'go' }}
+ uses: actions/setup-go@v4
+ with:
+ ${{ matrix.setup_tool }}-version: ${{ matrix.setup_version }}
+ - name: Set Up Node Environment
+ if: ${{ matrix.setup_tool == 'node' }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.setup_version }}
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ - name: Install Foundry Dependencies
+ run: forge install
+ - name: Run Build Server
+ run: ${{ matrix.build_cmd }}
+ working-directory: sdk-repo
+ - name: Run Server
+ run: ${{ matrix.server_cmd }}
+ working-directory: sdk-repo
+ - name: Wait for Server
+ run: |
+ sleep 10
+ curl -s http://localhost:9999/rpc -H "Content-type: application/json" -X POST -d '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' || (echo "Server not ready"; exit 1)
+ echo "Server is ready"
+ - name: Install Dependencies
+ run: forge install
+ - name: Run Tests
+ id: run_tests
+ continue-on-error: true
+ run: |
+ forge test --mp test/modules/BaseSig.t.sol
+ forge test --mp test/modules/Calls.t.sol
+ forge test --mp test/modules/Hooks.t.sol
+ forge test --mp test/modules/Implementation.t.sol
+ forge test --mp test/modules/Nonce.t.sol
+ forge test --mp test/modules/Payload.t.sol
+ forge test --mp test/Factory.t.sol
+ forge test --mp test/Guest.t.sol
+ forge test --mp test/Stage1Module.t.sol
+ forge test --mp test/Wallet.t.sol
+ env:
+ SEQ_SDK_RPC_URL_PREFIX: 'http://localhost:'
+ SEQ_SDK_RPC_URL_SUFFIX: '/rpc'
+ SEQ_SDK_RPC_MIN_PORT: '9999'
+ SEQ_SDK_RPC_MAX_PORT: '9999'
+ - name: Report Status
+ if: ${{ github.event_name != 'workflow_dispatch' }}
+ run: |
+ echo "status=${{ steps.run_tests.outcome == 'success' && 'success' || 'failure' }}" >> $GITHUB_OUTPUT
+ - name: Fail Job If Tests Fail
+ if: ${{ github.event_name != 'workflow_dispatch' && steps.run_tests.outcome == 'failure' }}
+ run: exit 1
+ - name: Update Status
+ if: ${{ github.event_name == 'workflow_dispatch' }}
+ continue-on-error: true
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const { owner, repo } = context;
+ const publicOwner = '0xsequence';
+ const publicRepo = ${{ matrix.repo_name }};
+ const repoUrl = ${{ matrix.repo_url }}
+ const commitSha = '${{ github.event.inputs.commit_hash }}';
+ const token = '${{ secrets.GITHUB_TOKEN }}';
+ const octokit = new Octokit({ auth: token });
+ const state = '${{ steps.run_tests.outcome == 'success' && 'success' || 'failure' }}';
+ await octokit.rest.repos.createCommitStatus({
+ owner: publicOwner,
+ repo: publicRepo,
+ sha: commitSha,
+ state: state,
+ target_url: repoUrl,
+ description: `The build was ${state}`
+ });
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/.gitmodules b/lib/signals-implicit-mode/lib/sequence-v3/.gitmodules
new file mode 100644
index 000000000..9d59c5672
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "lib/openzeppelin-contracts"]
+ path = lib/openzeppelin-contracts
+ url = https://github.com/OpenZeppelin/openzeppelin-contracts
+[submodule "lib/erc2470-libs"]
+ path = lib/erc2470-libs
+ url = https://github.com/ScreamingHawk/erc2470-libs
+[submodule "lib/forge-std"]
+ path = lib/forge-std
+ url = https://github.com/foundry-rs/forge-std
+[submodule "lib/account-abstraction"]
+ path = lib/account-abstraction
+ url = https://github.com/eth-infinitism/account-abstraction
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/.prettierignore b/lib/signals-implicit-mode/lib/sequence-v3/.prettierignore
new file mode 100644
index 000000000..f77cc0994
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/.prettierignore
@@ -0,0 +1,4 @@
+node_modules
+**/node_modules
+lib
+**/lib
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/.prettierrc b/lib/signals-implicit-mode/lib/sequence-v3/.prettierrc
new file mode 100644
index 000000000..6fe562bd5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/.prettierrc
@@ -0,0 +1,7 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "tabWidth": 2,
+ "printWidth": 100,
+ "trailingComma": "es5"
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/LICENSE b/lib/signals-implicit-mode/lib/sequence-v3/LICENSE
new file mode 100644
index 000000000..261eeb9e9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/README.md b/lib/signals-implicit-mode/lib/sequence-v3/README.md
new file mode 100644
index 000000000..6399141a1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/README.md
@@ -0,0 +1,53 @@
+# Sequence v3 wallet contracts
+
+Sequence v3 wallet contracts, with implicit and explicit smart sessions.
+
+## Development Setup
+
+Install dependencies
+
+```sh
+pnpm install
+```
+
+Git hooks will be automatically installed.
+
+## Testing
+
+Install the [Sequence v3 SDK](https://github.com/0xsequence/sequence.js) and run a server using the following command:
+
+```sh
+cd ../sequence.js
+pnpm build:packages
+pnpm dev:server
+```
+
+Copy the `env.sample` file to `.env` and set the environment variables.
+
+```sh
+cp .env.sample .env
+# Edit .env
+```
+
+Run tests
+
+```sh
+forge test
+```
+
+Run coverage (ignoring scripts and test files).
+
+```sh
+forge coverage --no-match-coverage "(script|test)"
+# Or to generate and view in browser
+forge coverage --no-match-coverage "(script|test)" --report lcov && genhtml -o report --branch-coverage lcov.info && py -m http.server -d report
+```
+
+Deploy contracts
+
+```sh
+forge script Deploy --rpc-url --broadcast
+```
+
+> [!NOTE]
+> Deployments use ERC-2470 for counter factual deployments.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/build_proxy.sh b/lib/signals-implicit-mode/lib/sequence-v3/build_proxy.sh
new file mode 100644
index 000000000..ce510d2b8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/build_proxy.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+SOL_VERSION="^0.8.0"
+HUFF_FILE="./src/Wallet.huff"
+SOL_OUT="./src/Wallet.sol"
+BYTECODE=$(huff -z -e paris "$HUFF_FILE" CONSTRUCTOR | sed 's/^0x//')
+HUFF_RAW=$(cat "$HUFF_FILE")
+cat > "$SOL_OUT" < Threshold
+
+All signature parts must meet their respective thresholds.
+
+### Payload order
+
+1. The first signature recovers the given Payload. If its threshold is met, then it generates an `imageHash` which corresponds to the root of a Merkle tree that defines the configuration of the wallet.
+
+2. Following signatures recover the `imageHash` of the previous signature, bundled within a payload of the `KIND_CONFIG_UPDATE` kind. They, in turn, recover to their own next `imageHash`.
+
+3. After the last signature has been recovered, the resulting `imageHash` must match the one defined by the contract.
+
+```
+┌──────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
+│Main payload │ │Config update payload│ │Config update payload│
+│(e.g. send tx)│ │ImageHash 1 │ │ImageHash 2 │
+└─────────────┬┘ └─▲──────────────────┬┘ └─▲──────────────────┬┘
+ │ │ │ │ │
+ Recover ──┤ │ Recover ──┤ │ Recover ──┤
+ │ │ │ │ │
+ ┌──────────▼┐ Generate │ ┌──────────▼┐ Generate │ ┌──────────▼┐
+ │ImageHash 1├──────────┘ │ImageHash 2├──────────┘ │ImageHash 3│
+ └───────────┘ └───────────┘ └─────┬─────┘
+ │
+ │
+ │
+ ╔═════▼═════╗
+ ║ Is valid? ║
+ ╚═══════════╝
+```
+
+### Checkpoint
+
+Each wallet configuration defines a checkpoint, checkpoints define a strict order in which these configurations can be used **in the context of a chained signature**, this acts as a form of replay protection that blocks the usage of a previous section of the state channel **in case the state channel ever repeats configurations**.
+
+For example, a wallet has a configuration with signers `A & B`, then it is updated to `A, B & C` and then updated back again to `A & B`. Afterwards, another update is queued, this time to `A, B & D`. Without the checkpoints, a malicious actor (C) may exploit the first update (where `C` was added) even if the wallet already evicted `C` as a signer.
+
+```
+ Checkpoint 2 -> 0 forbidden
+ ┌─────────────────────────────────────────────┐
+ │ │
+ x │
+┌───────────────┐ ┌─────────────────┐ ┌─────────────┴─┐ ┌─────────────────┐
+│Signers: A & B │ │Signers: A, B & C│ │Signers: A & B │ │Signers: A, B & D│
+│Checkpoint: 0 ├────▶│Checkpoint: 1 ├────▶│Checkpoint: 2 ├────▶│Checkpoint: 3 │
+└───────────────┘ └─────────────────┘ └───────────────┘ └─────────────────┘
+```
+
+## **3. Checkpointer**
+
+The checkpointer is an optional interface that helps wallets keep track of the latest valid configuration without publishing every intermediate step to all chains.
+
+Because wallets exist on multiple chains, unused networks often lag behind and accumulate old states. The checkpointer solves this by announcing the last known valid configuration. Anything older is automatically considered invalid.
+
+Wallet contracts don't specify how the checkpointer works internally. Its only job is to clearly state the latest valid configuration to prevent older states from being reused.
+
+### Disabled checkpointer
+
+Even when a checkpointer is defined by the configuration, the checkpointer has the capability to "disable" itself. This is useful for implementing escape hatches like timelocks or challenge periods, in case that the checkpointer becomes unresponsive or malicious. When the checkpointer announces a snapshot with `imageHash == bytes32(0)` it is considered disabled.
+
+Notice that there is **no built in mechanism** to force the checkpointer to become disabled from within the wallet, any mechanism that may challenge and disable the checkpointer must be implemented on the checkpointer contract.
+
+### Checkpointer data
+
+When a checkpointer is defined by the configuration, obtaining the latest snapshot from it requires passing a generic `data` field to the checkpointer contract. This `data` field is provided within the signature, and it is entirely opaque to the wallet contract.
+
+It wouldn't make sense for the checkpointer to be able to provide the snapshot directly from contract storage, as this would move the requirement of having to settle the state channel from the wallet contract to the checkpointer contract, instead, it is expected that the checkpointer will use the `data` field to validate a proof of the snapshot.
+
+The proof may be implemented as a simple merkle proof, a signature from a trusted party or T.E.E., a zk proof from a keystore rollup, or any other mechanism that may allow the checkpointer to provide a valid snapshot.
+
+### Checkpointer scenarios
+
+Different scenarios exist depending on the current state of the wallet, state channel and checkpointer, and the relationship between them.
+
+#### 1. Full sync
+
+This happens when the wallet contract configuration is set to the latest configuration defined by the state channel, and the checkpointer reports the same configuration.
+
+This scenario does not require the usage of chained signatures, as regular signatures are sufficient when the configuration that is being used matches the one defined by the contract.
+
+```
+ Checkpointer
+ ┌───────────────────────────────────────────────┐
+ │ Wallet │
+ │ ┌─────────────────────┐ │
+ │ ┌──────────────┐ │ ┌──────────────┐ │ │
+ │ │ Config A & B ├──────┼──▶ Config A & C │ │ │
+ │ └──────┬───────┘ │ └──────────────┘ │ │
+ │ │ └─────────────────────┘ │
+ └────────┼──────────────────────────────────────┘
+ │
+ ▼
+Old state - Irrelevant
+```
+
+> Notice that even if no chained signatures are used, the checkpointer is still required to provide a valid snapshot of the latest configuration.
+
+#### 2. Checkpointer Ahead, Wallet Behind
+
+The state channel is ahead of the wallet contract, but the checkpointer knows about the latest configuration. In this scenario, the checkpointer provides a snapshot for the latest configuration, and the wallet **must** use a chained signature to sign the payload, using that latest configuration.
+
+```
+ Checkpointer
+ ┌────────────────────────────────────────────────────────────────────┐
+ │ Wallet │
+ │ ┌─────────────────────┐ │
+ │ ┌──────────────┐ │ ┌──────────────┐ │ ┌──────────────┐ │
+ │ │ Config A & B ├──────┼──▶ Config A & C ├───┼─────▶ Config D & C │ │
+ │ └──────┬───────┘ │ └──────────────┘ │ └───────┬──────┘ │
+ │ │ └─────────────────────┘ │ │
+ └────────┼──────────────────────────────────────────────────┼────────┘
+ │ │
+ ▼ ▼
+Old state - Irrelevant Latest state
+```
+
+#### 3. Checkpointer Behind, Wallet Synced
+
+The checkpointer is behind the wallet contract, and there are no pending configurations in the state channel. In this scenario, the checkpointer will provide a snapshot with a checkpoint that is behind the wallet contract, and this will make the wallet contract ignore the checkpointer's snapshot.
+
+This scenario may happen if the wallet is manually updated to a new configuration without notifying the checkpointer, or if the checkpointer hasn't had time to "react" and "catch up" with the wallet contract. It may be possible that the checkpointer is offline, and not reacting to any configuration changes.
+
+```
+ Checkpointer Wallet
+ ┌──────────────────┐ ┌─────────────────────┐
+ │ ┌──────────────┐ │ │ ┌──────────────┐ │
+ │ │ Config A & B ├─┼────┼──▶ Config A & C │ │
+ │ └──────┬───────┘ │ │ └──────────────┘ │
+ └────────┼─────────┘ └─────────────────────┘
+ │
+ │
+ ▼
+Old state - Irrelevant
+```
+
+#### 4. Wallet Behind, Checkpointer Further Behind
+
+The checkpointer is behind the wallet contract, and there are pending configurations in the state channel. This scenario is very similar to the previous one, the only difference is that the wallet will use a chained signature to sign the payload, using the latest configuration.
+
+Even if the wallet uses a chained signature, since the checkpointer's snapshot checkpoint is behind the wallet contract, the wallet will not use the checkpointer's snapshot.
+
+```
+ Checkpointer Wallet
+ ┌──────────────────┐ ┌─────────────────────┐
+ │ ┌──────────────┐ │ │ ┌──────────────┐ │ ┌──────────────┐
+ │ │ Config A & B ├─┼────┼──▶ Config A & C ├───┼─────▶ Config B & C │
+ │ └──────┬───────┘ │ │ └──────────────┘ │ └──────┬───────┘
+ └────────┼─────────┘ └─────────────────────┘ │
+ │ │
+ │ │
+ ▼ ▼
+Old state - Irrelevant Latest state
+```
+
+#### 5. Checkpointer Ahead, Wallet Behind, State Channel Further Ahead
+
+The state channel has multiple configuration updates, the checkpointer is ahead of the wallet contract, yet the state channel goes further than the checkpointer. This scenario may happen if the latest configuration update happened recently and the checkpointer hasn't updated yet.
+
+In this scenario, the checkpointer provides a snapshot, the wallet contract enforces a chained signature to sign the payload, forcing that the chained signature, at some point, goes over the checkpointer's snapshot.
+
+```
+ Checkpointer
+ ┌────────────────────────────────────────────────────────────────────┐
+ │ Wallet │
+ │ ┌─────────────────────┐ │
+ │ ┌──────────────┐ │ ┌──────────────┐ │ ┌──────────────┐ │ ┌──────────────┐
+ │ │ Config A & B ├──────┼──▶ Config A & C ├───┼─────▶ Config D & C ├─┼───────▶ Config D & E │
+ │ └──────┬───────┘ │ └──────────────┘ │ └──────────────┘ │ └──────┬───────┘
+ │ │ └─────────────────────┘ │ │
+ └────────┼───────────────────────────────────────────────────────────┘ │
+ │ │
+ ▼ ▼
+Old state - Irrelevant Latest state
+```
+
+#### 6. Wallet Synced, Checkpointer Dangling Ahead
+
+The checkpointer may report a future configuration that is not part of the state channel. This may happen if the checkpointer is misbehaving, malicious, or there is a state channel update that has only been revealed to the checkpointer.
+
+In this scenario, the checkpointer contract **must** provide with an escape hatch mechanism for either:
+
+1. Provide the link to the dangling configuration
+2. Disable itself
+
+```
+ Checkpointer
+ ┌────────────────────────────────────────────────────────────────────┐
+ │ Wallet │
+ │ ┌─────────────────────┐ │
+ │ ┌──────────────┐ │ ┌──────────────┐ │ ┌──────────────┐ │
+ │ │ Config A & B ├──────┼──▶ Config A & C ├───┼─x │ Config D & C │ │
+ │ └──────┬───────┘ │ └───────┬──────┘ │ └───────┬──────┘ │
+ │ │ └──────────┼──────────┘ │ │
+ └────────┼─────────────────────────┼────────────────────────┼────────┘
+ │ │ │
+ ▼ ▼ ▼
+Old state - Irrelevant Latest state Dangling, not linked
+```
+
+### Checkpointer signature format
+
+Signatures that involve a checkpointer contain two additional pieces of data, the "checkpointer address" that is used to identify the checkpointer (and to be able to reconstruct the merkle root), and the "checkpointer data" which is needed to obtain the snapshot from the checkpointer.
+
+#### Non-chained signatures
+
+When non-chained signatures are used, the signature flag **must** have the `X1XX XXXX` bit set (`flag & 0x08 == 0x08`), this signals to the wallet contract that the signature involves a checkpointer, afterwards fixed 20 bytes are read to obtain the checkpointer address, and the next 3 bytes are read to obtain the checkpointer data size, after which the checkpointer data is read.
+
+```
+ ┌───▶ 1 byte global flag
+ │ must have the 2nd bit
+ │ set to 1 to signal a chained ┌───▶ 3 bytes define the size
+ │ signature │ of the checkpointer data
+ │ │
+──┴─ ───┴──
+0x40 6974206973207265616c6C792073756E6E791aDd 001271 6b656570206275696c64696e67...
+ ──┬───────────────────────────────────── ─┬───────────────────────────
+ │ │
+ └─▶ 20 byte address └─▶ Dynamic size checkpointer
+ determines the address data
+ of the checkpointer
+```
+
+#### Chained signatures
+
+If chained signatures are used, then the encoding becomes slightly more complex. The reason for this is that the **only** checkpointer that is used is the one that is defined by the wallet contract, **checkpointers provided by the state channel are ignored**.
+
+This is intended behavior, as the checkpointer is in charge of overseeing the state channel, thus it wouldn't be safe for the state channel to be able to provide a checkpointer, as it could self-authorize the state channel. This would negate the purpose of having a checkpointer in the first place.
+
+There is a challenge with this, when a chained signature is encoded, the configuration that corresponds to the wallet contract is provided **at the end of the chain**, which is a problem, because we need to obtain the snapshot at the beginning of the chain, in order to validate if the state channel ever "goes over" the snapshot provided by the checkpointer.
+
+Additionally, intermediary configurations need to have their checkpointers provided, as it is needed to reconstruct the merkle root. However no checkpointer data is needed, as these intermediate checkpointers are not called.
+
+To solve this, when a chained signature is used, and the onchain configuration contains a checkpointer, the checkpointer of the **last** configuration is moved at the beginning of the chain, alongside its checkpointer data, and no checkpointer data is provided for the intermediate signature parts.
+
+```
+ ┌─▶ 2nd. bit signals checkpointer ┌──▶ The checkpointer and data is only
+ │ │ provided once, as part of the
+ │ ┌▶ 8th. bit signals chained │ chained signatures, and not of
+ ┴ ┴ │ the individual parts
+ 0100 0001 │
+ ▲ ┌───────────────────────────────────┴─────────────────────────────────────────┐
+ │ │ 3 byte Size │
+ ──┴─│ ────── │
+ 0x41│6974206973207265616c6C792073756E6E791aDd 001271 6b656570206275696c64696e67...│─┐
+ │──────────────────────────────────────── ────────────────────────────────────│ │
+ │Checkpointer address □ Checkpointer data │ │
+ └─────────────────────╫───────────────────────────────────────────────────────┘ │
+╔═══════════════════════════╝ │
+║ ┌────────────────────────────────────────────────────────────────────────────────┘
+║ │
+║ │ Payload signature ┌─▶ No checkpointer data
+║ │ ┌───────────────────────────────────────────┼───────────────────┐
+║ │ │ x │
+║ └───▶│44 6974206973207265616c6C792073756E6E791aDd 03 01 5151515151...│─┐
+║ │─┬───────────────────────────────────────── │ │
+║ └─┼─────────────────────────────────────────────────────────────┘ │
+║ │ │
+║ └───▶ Signature requires checkpointer │
+║ but no checkpointer data is │
+║ required as it is only for root │
+║ recovery │
+║ │
+║ Checkpointer may or may not match │
+║ │
+║ ┌──────────────────────────────────────────────────────┐ │
+║ ┌─────┤ Intermediary signatures follow the previous format ├─────────┘
+║ │ └──────────────────────────────────────────────────────┘
+║ │
+║ │ Final signature
+║ │ ┌────────────────────────────────┐
+║ │ │ │
+║ └───▶│04 03 01 5252525252552525252... │
+║ │ x ───────────────────┬── │
+║ └──┼─────────────────────────┼───┘
+║ │ │
+║ └▶ No checkpointer │
+║ No checkpointer data └────▶ Regular signature body
+║
+╚════════════▷ Recovery uses the checkpointer
+ that got at the start of the
+ chained signature
+```
+
+### Checkpointer control flow
+
+In summary, only the checkpointer that is defined by the wallet contract is used. If a non-chained signature is used, it has to either match the checkpointer's snapshot, or it must be behind the wallet contract.
+
+If a chained signature is used, then at some point during the chain, the snapshot provided by the checkpointer must match with one of the recovered configurations, this may also happen at the final signature. If this does not happen, the final signature (that corresponds to the wallet contract) **must** be ahead of the checkpointer's snapshot.
+
+```
+ ╔═══════════════════╗
+ ║ ║
+ ║ Validation ║
+ ║ start ║
+ ║ ║
+ ╚═════════╤═════════╝
+ │
+ │
+ │
+ ┌─────────▼─────────┐
+ │ │
+ │ Obtain snapshot │
+ │ │
+ │ │
+ └─────────┬─────────┘
+ │
+ │
+ │
+ ╔═══════════════════╗ ╭─────────▼─────────╮
+ ║ ║ │ Is snapshot │
+ ║ Approved by ║ Yes│ equal to │
+ ║ checkpointer ◀────────┤ bytes32(0)? │
+ ║ ║ │ │
+ ╚═══════════════════╝ ╰─────────┬─────────╯
+ │No
+ │
+ │
+ ╭─────────▼─────────╮
+ │ │
+ │ Is chained │ Yes
+ │ signature? ├────────────────╮
+ │ │ │
+ ╰─────────┬─────────╯ │
+ │No │
+ │ │
+ │ │
+ ╔═══════════════════╗ ┌─────────▼─────────┐ │
+ ║ ║ │ │ │
+ ║ Rejected by ║ │ Recover │ │
+ ║ checkpointer ║ │ image hash │ │
+ ║ ║ │ │ │
+ ╚═════════▲═════════╝ └─────────┬─────────┘ │
+ │ │ │
+ │ │ │
+ │No │ │
+ ╭─────────┴─────────╮ ╭─────────▼─────────╮ │
+ │ │ │ │ │
+ │ Checkpoint below │ No │ Matches │ │
+ │ snapshot? ◀────────┤ snapshot? │ │
+ │ │ │ │ │
+ ╰─────────┬─────────╯ ╰─────────┬─────────╯ │
+ │Yes │Yes │
+ │ │ │
+ │ │ │
+ │ ╔═════════▼═════════╗ │
+ │ ║ ║ │
+ │ ║ Approved by ║ │
+ └──────────────────▶ checkpointer ║ │
+ ║ ║ │
+ ╚═══════════════════╝ │
+ │
+ │
+ │
+ ┌───────────────▼───┐
+ │ │
+ │ Recover │
+ ┌──────────────────▶ image hash │
+ │ │ │
+ │ └─────────┬─────────┘
+ │ │
+ │ │
+ │No │
+ ╭─────────┴─────────╮ ╭─────────▼─────────╮
+ │ │ │ │
+ Yes│ Was the last │ No │ Matches │
+ ┌──────────────────┤ signature part? ◀────────┤ snapshot? │
+ │ │ │ │ │
+ │ ╰─────────▲─────────╯ ╰─────────┬─────────╯
+ │ │ │Yes
+ │ │ │
+ │ │ │
+╭─────────▼─────────╮ │ ┌─────────▼─────────┐
+│ │ │ │ │
+│ Was the snapshot │Yes │ │ Consume │
+│ consumed? ├─────────────┐ └──────────────────┤ snapshot │
+│ │ │ │ │
+╰─────────┬─────────╯ │ └───────────────────┘
+ │No │
+ │ │
+ │ │
+╭─────────▼─────────╮ ╔════▼══════════════╗
+│ │ ║ ║
+│ Last checkpoint │Yes ║ Approved by ║
+│ below snapshot? ├────────▶ checkpointer ║
+│ │ ║ ║
+╰─────────┬─────────╯ ╚═══════════════════╝
+ │No
+ │
+ │
+╔═════════▼═════════╗
+║ ║
+║ Rejected by ║
+║ checkpointer ║
+║ ║
+╚═══════════════════╝
+```
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/docs/CONFIGURATIONS.md b/lib/signals-implicit-mode/lib/sequence-v3/docs/CONFIGURATIONS.md
new file mode 100644
index 000000000..8d0c7d519
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/docs/CONFIGURATIONS.md
@@ -0,0 +1,279 @@
+# Sequence chained signatures
+
+This document provides a description on how the Sequence wallet contracts define and handle sets of signers, checkpoints, extensions and other parameters that fall within the scope of its "configuration".
+
+## **1. Overview**
+
+All Sequence wallets have a defined "configuration", this is the set of parameters that governs the wallet's behavior.
+
+The configuration includes:
+
+- The threshold needed to authorize a transaction.
+- The set of signers, and their corresponding weights.
+- The current "checkpoint", which determines the order of configuration updates.
+- Any "extensions" that are enabled, with their corresponding parameters.
+- The "checkpointer" contract, which acts as a connector for a keystore rollup.
+- Any pre-authorized transactions or messages, that are considered signed by the wallet.
+
+All these parameters are encoded into leaves of a merkle tree, of which the root is stored either as counter-factual information during wallet creation (as the salt of the `CREATE2` opcode), or directly within the contract storage; this "merkle root" is internally referred as the `imageHash` of the wallet.
+
+Since the wallet contract does not have direct access to the configuration, every time a signature is provided, the signature must provide both the "signature parts" that may be needed for the individual signers, as well as the "merkle proof" that allows the wallet contract to reconstruct the `imageHash` and thus validate the signature.
+
+## **2. Tree structure**
+
+The tree is a **sparse binary merkle tree**, this allows for more frequently accessed parameters to be stored closer to the root, making merkle proofs more efficient. Some elements like the `checkpointer`, `checkpoint` and `threshold` have fixed positions at the top of the tree, afterwards the other leaves can be arranged in any order.
+
+The top of the tree looks like:
+
+```
+imageHash = keccak256(
+ keccak256(
+ keccak256(
+ ...leaves,
+ threshold
+ ),
+ checkpoint
+ ),
+ checkpointer || address(0)
+)
+```
+
+The `checkpointer` is optional, if it is not provided it still has to be included in the merkle tree, it will be automatically set to `address(0)` if the signature flags do not set the `CHECKPOINTER` bit.
+
+```
+ ┌────────────────┐
+ │ │
+ │ Image hash │
+ │ │
+ └───▲────────▲───┘
+ │ │
+ ┌───┘ └────┐
+ │ ┌──────────┼───────────┐
+ ╭────┴───╮ │ ┌───────┴────────┐ │
+ │ │ │ │ │ ├────▶ This section is
+ │ │ │ │ Checkpointer │ │ always in the tree.
+ │ │ │ │ │ │
+ ╰─▲────▲─╯ │ └────────────────┘ │ It won't be shown
+ │ │ │ │ in the other diagrams.
+ │ └────┼──────────┐ │
+ │ │ │ │
+ ╭─┴──────╮ │ ┌───────┴────────┐ │
+ │ │ │ │ │ │
+ │ │ │ │ Checkpoint │ │
+ │ │ │ │ │ │
+ ╰─▲────▲─╯ │ └────────────────┘ │
+ │ │ │ │
+ │ └────┼──────────┐ │
+ │ │ │ │
+╔═════════╧══════╗ │ ┌───────┴────────┐ │
+║ ... rest ║ │ │ │ │
+║ of the tree ║ │ │ Threshold │ │
+║ ║ │ │ │ │
+╚════════════════╝ │ └────────────────┘ │
+ └──────────────────────┘
+```
+
+## **3. Leaf types**
+
+### 3.1 Signer leaf
+
+Signer leaves are used to specify signer addresses, meaning that when a valid signature is provided, the wallet will count their weight towards the threshold. Signer leaves do not specify if they are ERC1271 signers or not, instead this is determined when the signature is encoded.
+
+```
+ ┌────────────────┐
+ │ │
+ │ Image hash │
+ │ │
+ └───▲────────▲───┘
+ │ │
+ ┌───┘ └──────┐
+ │ │
+ ╭────┴───╮ ╔═════════╧═════════╗
+ │ │ ║Checkpointer: 0x ║
+ │ │ ║Checkpoint: 0 ║
+ │ │ ║Threshold: 1 ║
+ ╰─▲────▲─╯ ╚═══════════════════╝
+ │ │
+ ┌───────┘ └──────┐
+ │ │
+ │ │
+┌────────────────┐ ┌────────────────┐
+│ Signer 0xaaa │ │ Signer 0xbbb │
+│ Weight: 1 │ │ Weight: 1 │
+│ │ │ │
+└────────────────┘ └────────────────┘
+```
+
+The hash of a signer leaf is computed as:
+
+```
+leaf = keccak256(
+ "Sequence signer:\n",
+ address,
+ weight
+)
+```
+
+> Notice that any address that is registered **more than once** will be counted **multiple times** in the threshold.
+
+### 3.2 Hardcoded signature leaf
+
+Hardcoded signature leaves allow for the configuration to automatically sign a specific payload, this is useful for pre-approving transactions, for example pre-approving an approval for an ERC20 at the same time as the wallet is created.
+
+If a payload hash matches the hardcoded hash (subdigest), the weight counted towards the threshold will automatically be bumped to `type(uint256).max`, ensuring the signature to be valid.
+
+```
+ ┌────────────────┐
+ │ │
+ │ Image hash │
+ │ │
+ └───▲────────▲───┘
+ │ │
+ ┌───────┘ └────────┐
+ │ │
+┌───────┴────────┐ ╔═════════╧═════════╗
+│ Subdigest: │ ║Checkpointer: 0x ║
+│ 0x11223344 │ ║Checkpoint: 0 ║
+│ │ ║Threshold: 1 ║
+└────────────────┘ ╚═══════════════════╝
+```
+
+The hash of a hardcoded signature leaf is computed as:
+
+```
+leaf = keccak256(
+ "Sequence static digest:\n",
+ subdigest
+)
+```
+
+### 3.3 Any address hardcoded signature leaf
+
+This works very similarly to the hardcoded signature leaf, but the hash of the payload is computed setting its ERC712 domain separator to `address(0)` instead of the wallet's address.
+
+This allows for pre-approving transactions before the wallet has counterfactually been defined, otherwise attempting to compute the hash would require the wallet's address to be known beforehand, and determining the address would require the hash to be known beforehand, causing a recursive dependency.
+
+After a wallet is created, it is recommended to use the hardcoded signature leaf instead, as it is more efficient.
+
+The hash of an any address hardcoded signature leaf is computed as:
+
+```
+leaf = keccak256(
+ "Sequence any address subdigest:\n",
+ subdigest
+)
+```
+
+### 3.4 Nested configuration leaf
+
+Nested configuration leaves are used to specify nested configuration trees, this allows for certain sets of signers to be grouped in such a way that their signing power is limited by a threshold. It can also allow to augment the signing power of a set of signers, by making them have no signing power individually but still be able to sign as a group.
+
+They have their own internal thresholds, internally they work exactly as the parent "main" tree, but externally they can only contribute their own weight.
+
+```
+ ┌────────────────┐
+ │ │
+ │ Image hash │
+ │ │
+ └───▲────────▲───┘
+ │ │
+ ┌───┘ └──────┐
+ │ │
+ ╭────┴───╮ ╔═════════╧═════════╗
+ │ │ ║ Checkpointer: 0x ║
+ │ │ ║ Checkpoint: 0 ║
+ │ │ ║ Threshold: 2 ║
+ ╰─▲────▲─╯ ╚═══════════════════╝
+ │ │
+ ┌──────┘ └──────┐
+ │ │ ────┐
+┌──────────┴─────┐ ┌─────┴──────────┐ │
+│ Signer 0xaaa │ │ Threshold: 1 │ ├─▶ The maximum weight
+│ Weight: 1 │ │ Weight: 1 │ │ of 0xbbb and 0xccc
+│ │ │ │ │ can't exceed 1
+└────────────────┘ └─────▲────▲─────┘ │
+ │ │ │ Forced either of
+ ┌──────┘ └──────┐ │ them to be combined
+ │ │ │ with 0xaaa
+ ┌──────────┴─────┐ ┌─────┴──────────┐ │
+ │ Signer: 0xbbb │ │ Signer 0xccc │ │
+ │ Weight: 1 │ │ Weight: 2 │ │
+ │ │ │ │ │
+ └────────────────┘ └────────────────┘ │
+ ────┘
+```
+
+The hash of a nested tree is computed as:
+
+```
+leaf = keccak256(
+ "Sequence nested config:\n",
+ node,
+ threshold,
+ weight
+)
+```
+
+### 3.5 Sapient Signer Leaf
+
+Sapient signer leaves work similarly to Signer leaves, but have 3 key distinctions:
+
+1. Sapient signers **must** always be smart contracts, EOA signers are not allowed
+2. Sapient signers **do not** use the ERC1271 interface, instead they get passed a fully decoded `Payload` to sign
+3. Sapient signatures are not validated, they are **recovered** into a hash
+
+When a sapient signer leaf is added to a configuration, it must define its `address`, `weight` and `imageHash`. The `imageHash` represents the expected value that the sapient signer **must recover** for the signature to be valid.
+
+This allows sapient signers to act as **extensions** of the configuration tree, they can define their own leaf types and overall structures, alongside arbitrary logic. This allows for extensions to be configured per wallet without having to rely on the contract storage of the extension, as the definition of the configuration resides in the same `imageHash`.
+
+```
+ ┌────────────────┐
+ │ │
+ │ Image hash │
+ │ │
+ └───▲────────▲───┘
+ │ │
+ ┌───┘ └──────┐
+ │ │
+ ╭────┴───╮ ╔═════════╧═════════╗
+ │ │ ║ Checkpointer: 0x ║
+ │ │ ║ Checkpoint: 0 ║
+ │ │ ║ Threshold: 2 ║
+ ╰─▲────▲─╯ ╚═══════════════════╝
+ │ │
+ ┌──────┘ └──────┐
+ │ │ ────┐
+ ┌──────────┴─────┐ ┌─────┴──────────┐ ├─▶ The passkey sapient
+ │ Signer 0xaaa │ │ Passkey │ │ signer uses its tree
+ │ Weight: 1 │ │ weight: 1 │ │ to define public
+ │ │ │imageHash: 0xabc│ │ keys and
+ └────────────────┘ └─────▲────▲─────┘ │ configuration
+ │ │ │ parameters.
+ ┌───────────────┘ └───────────────┐ │
+ │ │ │ Signatures must be
+ ╭─────┴──╮ ╭──┴─────╮ │ able to recover the
+ │ │ │ │ │ inner root of the
+ │ │ │ │ │ tree to be
+ │ │ │ │ │ considered valid.
+ ╰─▲────▲─╯ ╰─▲────▲─╯ │
+ │ │ │ │ │
+ ┌──────┘ └──────┐ ┌──────┘ └──────┐ │
+ │ │ │ │ │
+┌────────┴───────┐ ┌───────┴────────┐ ┌────────┴───────┐ ┌───────┴────────┐ │
+│ │ │ │ │ Require user │ │ │ │
+│ Pubkey X │ │ Pubkey Y │ │ verification │ │ Metadata │ │
+│ │ │ │ │ true/false │ │ │ │
+└────────────────┘ └────────────────┘ └────────────────┘ └────────────────┘ │
+ ────┘
+```
+
+The hash of a sapient signer leaf is:
+
+```
+leaf = keccak256(
+ "Sequence sapient config:\n",
+ address,
+ weight,
+ imageHash
+)
+```
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/docs/PAYLOAD.md b/lib/signals-implicit-mode/lib/sequence-v3/docs/PAYLOAD.md
new file mode 100644
index 000000000..61d71e55f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/docs/PAYLOAD.md
@@ -0,0 +1,392 @@
+# Sequence Payload System Documentation
+
+This document provides a comprehensive overview of how the Sequence wallet contracts encode, decode, and execute payloads. It explains the payload structure, encoding schemes, execution flow, and how payloads integrate with the broader signature and configuration systems.
+
+---
+
+## **1. Overview**
+
+The Sequence payload system is the core mechanism through which wallets execute batched operations. Payloads are encoded data structures that contain:
+
+- **Transaction calls** with target addresses, values, and calldata
+- **Configuration updates** for wallet parameters
+- **Message validations** for arbitrary data signing
+- **Digest verifications** for ERC-1271 compatibility
+
+Payloads are designed to be:
+
+1. **Gas-efficient** through compact binary encoding
+2. **Flexible** to support various operation types
+3. **Secure** through EIP-712 structured hashing
+4. **Batchable** to execute multiple operations atomically
+
+---
+
+## **2. Payload Types**
+
+The system supports four distinct payload kinds, each serving different purposes:
+
+### **2.1 Transaction Payloads (`KIND_TRANSACTIONS = 0x00`)**
+
+Transaction payloads contain batched calls to external contracts or self-execution logic. These are the most common payload type and support:
+
+- Multiple contract calls in sequence
+- Value transfers with calls
+- Delegate calls for extension execution
+- Gas limit specifications
+- Error handling behaviors
+- Fallback-only execution modes
+
+### **2.2 Message Payloads (`KIND_MESSAGE = 0x01`)**
+
+Message payloads allow wallets to sign arbitrary data for off-chain verification. This is useful for:
+
+- Meta-transactions
+- Off-chain authorization
+- Cross-chain message signing
+- General-purpose data signing
+
+### **2.3 Configuration Update Payloads (`KIND_CONFIG_UPDATE = 0x02`)**
+
+Configuration update payloads enable wallet reconfiguration through:
+
+- Signer set modifications
+- Threshold adjustments
+- Extension enablement/disablement
+- Checkpoint updates
+
+### **2.4 Digest Payloads (`KIND_DIGEST = 0x03`)**
+
+Digest payloads provide ERC-1271 compatibility by allowing wallets to validate pre-computed message hashes.
+
+---
+
+## **3. Payload Structure**
+
+### **3.1 Core Payload Structure**
+
+All payloads share a common structure defined by the `Decoded` struct:
+
+```solidity
+struct Decoded {
+ uint8 kind; // Payload type identifier
+ bool noChainId; // Chain ID inclusion flag
+ // Transaction-specific fields
+ Call[] calls; // Array of call operations
+ uint256 space; // Nonce space identifier
+ uint256 nonce; // Nonce value for replay protection
+ // Message-specific fields
+ bytes message; // Raw message data
+ // Configuration-specific fields
+ bytes32 imageHash; // New configuration hash
+ // Digest-specific fields
+ bytes32 digest; // Pre-computed message hash
+ // Common fields
+ address[] parentWallets; // Parent wallet addresses
+}
+```
+
+### **3.2 Call Structure**
+
+Individual calls within transaction payloads are defined by the `Call` struct:
+
+```solidity
+struct Call {
+ address to; // Target contract address
+ uint256 value; // ETH value to send
+ bytes data; // Calldata for the call
+ uint256 gasLimit; // Gas limit for execution
+ bool delegateCall; // Delegate call flag
+ bool onlyFallback; // Fallback-only execution
+ uint256 behaviorOnError; // Error handling strategy
+}
+```
+
+---
+
+## **4. Payload Encoding**
+
+### **4.1 Transaction Payload Encoding**
+
+Transaction payloads use a compact binary encoding scheme optimized for gas efficiency. The encoding follows this structure:
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ Global Flag (1 byte) │
+│ ┌─────────────────────────────────────────────────────────────────────────┐ │
+│ │ Bit 0: Space flag (0 = read space, 1 = space is 0) │ │
+│ │ Bits 1-3: Nonce size (0-7 bytes) │ │
+│ │ Bit 4: Single call flag (0 = multiple calls, 1 = single call) │ │
+│ │ Bit 5: Call count size (0 = 1 byte, 1 = 2 bytes) │ │
+│ │ Bits 6-7: Reserved │ │
+│ └─────────────────────────────────────────────────────────────────────────┘ │
+├─────────────────────────────────────────────────────────────────────────────┤
+│ Space (0 or 20 bytes) - only if space flag is 0 │
+├─────────────────────────────────────────────────────────────────────────────┤
+│ Nonce (0-7 bytes) - size determined by bits 1-3 │
+├─────────────────────────────────────────────────────────────────────────────┤
+│ Call Count (1-2 bytes) - size determined by bit 5 │
+├─────────────────────────────────────────────────────────────────────────────┤
+│ Call Array (call count length) │
+│ ┌─────────────────────────────────────────────────────────────────────────┐ │
+│ │ Call Flags (1 byte) │ │
+│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
+│ │ │ Bit 0: Self-call flag (0 = external, 1 = self) │ │ │
+│ │ │ Bit 1: Value flag (0 = no value, 1 = has value) │ │ │
+│ │ │ Bit 2: Data flag (0 = no data, 1 = has data) │ │ │
+│ │ │ Bit 3: Gas limit flag (0 = no limit, 1 = has limit) │ │ │
+│ │ │ Bit 4: Delegate call flag │ │ │
+│ │ │ Bit 5: Fallback-only flag │ │ │
+│ │ │ Bits 6-7: Behavior on error (00=ignore, 01=revert, 10=abort) │ │ │
+│ │ └─────────────────────────────────────────────────────────────────────┘ │ │
+│ ├─────────────────────────────────────────────────────────────────────────┤ │
+│ │ Target Address (0 or 20 bytes) - only if not self-call │ │
+│ ├─────────────────────────────────────────────────────────────────────────┤ │
+│ │ Value (0 or 32 bytes) - only if value flag is set │ │
+│ ├─────────────────────────────────────────────────────────────────────────┤ │
+│ │ Data Size (0 or 3 bytes) - only if data flag is set │ │
+│ ├─────────────────────────────────────────────────────────────────────────┤ │
+│ │ Data (0 or N bytes) - only if data flag is set │ │
+│ ├─────────────────────────────────────────────────────────────────────────┤ │
+│ │ Gas Limit (0 or 32 bytes) - only if gas limit flag is set │ │
+│ └─────────────────────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────────────────┘
+```
+
+### **4.2 Global Flag Breakdown**
+
+The global flag byte controls the overall payload structure:
+
+```
+Global Flag: [7][6][5][4][3][2][1][0]
+ │ │ │ │ │ │ │ └── [0] Space flag
+ │ │ │ │ │ │ └───── [1][0] Nonce size
+ │ │ │ │ │ └──────── [2][1] Nonce size
+ │ │ │ │ └─────────── [3][2] Nonce size
+ │ │ │ └────────────── [4] Single call flag
+ │ │ └───────────────── [5] Call count size
+ │ └──────────────────── [6] Reserved
+ └─────────────────────── [7] Reserved
+```
+
+**Space Flag (Bit 0):**
+
+- `0`: Read 20-byte space address from payload
+- `1`: Set space to 0 (default space)
+
+**Nonce Size (Bits 1-3):**
+
+- `000`: No nonce (nonce = 0)
+- `001`: 1-byte nonce
+- `010`: 2-byte nonce
+- `011`: 3-byte nonce
+- `100`: 4-byte nonce
+- `101`: 5-byte nonce
+- `110`: 6-byte nonce
+- `111`: 7-byte nonce
+
+**Single Call Flag (Bit 4):**
+
+- `0`: Multiple calls (read call count)
+- `1`: Single call (call count = 1)
+
+**Call Count Size (Bit 5):**
+
+- `0`: Call count stored in 1 byte
+- `1`: Call count stored in 2 bytes
+
+### **4.3 Call Flags Breakdown**
+
+Each call begins with a flags byte that controls its execution parameters:
+
+```
+Call Flags: [7][6][5][4][3][2][1][0]
+ │ │ │ │ │ │ │ └─── [0] Self-call flag
+ │ │ │ │ │ │ └────── [1] Value flag
+ │ │ │ │ │ └───────── [2] Data flag
+ │ │ │ │ └──────────── [3] Gas limit flag
+ │ │ │ └─────────────── [4] Delegate call flag
+ │ │ └────────────────── [5] Fallback-only flag
+ │ └───────────────────── [6][0] Behavior on error
+ └──────────────────────── [7][1] Behavior on error
+```
+
+**Self-call Flag (Bit 0):**
+
+- `0`: External call (read target address)
+- `1`: Self-call (target = address(this))
+
+**Value Flag (Bit 1):**
+
+- `0`: No ETH value
+- `1`: Read 32-byte value from payload
+
+**Data Flag (Bit 2):**
+
+- `0`: No calldata
+- `1`: Read 3-byte data size + N bytes of data
+
+**Gas Limit Flag (Bit 3):**
+
+- `0`: Use remaining gas
+- `1`: Read 32-byte gas limit from payload
+
+**Delegate Call Flag (Bit 4):**
+
+- `0`: Regular call
+- `1`: Delegate call
+
+**Fallback-only Flag (Bit 5):**
+
+- `0`: Execute normally
+- `1`: Only execute if previous call failed
+
+**Behavior on Error (Bits 6-7):**
+
+- `00`: Ignore error, continue execution
+- `01`: Revert entire transaction
+- `10`: Abort execution, stop processing
+- `11`: Reserved
+
+---
+
+## **5. Payload Execution**
+
+### **5.1 Execution Flow**
+
+The payload execution follows this sequence:
+
+1. **Decode Payload**: Parse the binary payload into structured data
+2. **Nonce Validation**: Consume the nonce to prevent replay attacks
+3. **Signature Verification**: Validate the signature against the payload
+4. **Call Execution**: Execute each call in sequence
+5. **Error Handling**: Apply error handling based on call configuration
+
+### **5.2 Call Execution Modes**
+
+#### **Regular Calls**
+
+Standard contract calls that execute with the specified parameters and return control to the wallet.
+
+#### **Delegate Calls**
+
+Execute code in the context of the wallet contract, allowing extensions to modify wallet state.
+
+#### **Fallback-only Calls**
+
+Only execute when the immediately preceding call fails (and has the `BEHAVIOR_IGNORE_ERROR` behavior), enabling conditional execution flows. See Error Handling Strategies below.
+
+### **5.3 Error Handling Strategies**
+
+The system provides three error handling behaviors:
+
+1. **Ignore Error (`BEHAVIOR_IGNORE_ERROR`)**
+ - Continue execution with subsequent calls
+ - Set error flag for fallback-only calls
+ - Emit `CallFailed` event
+
+2. **Revert on Error (`BEHAVIOR_REVERT_ON_ERROR`)**
+ - Revert entire transaction
+ - Rollback all state changes
+ - Emit `Reverted` error
+
+3. **Abort on Error (`BEHAVIOR_ABORT_ON_ERROR`)**
+ - Stop processing remaining calls
+ - Keep successful call results
+ - Emit `CallAborted` event
+
+---
+
+## **6. EIP-712 Integration**
+
+### **6.1 Domain Separator**
+
+Payloads use EIP-712 for structured hashing with the domain:
+
+```
+EIP712Domain(
+ name: "Sequence Wallet"
+ version: "3"
+ chainId: block.chainid (or 0 if noChainId)
+ verifyingContract: wallet address
+)
+```
+
+### **6.2 Type Hashes**
+
+Each payload type has a specific type hash:
+
+- **Calls**: `keccak256("Calls(Call[] calls,uint256 space,uint256 nonce,address[] wallets)")`
+- **Message**: `keccak256("Message(bytes message,address[] wallets)")`
+- **ConfigUpdate**: `keccak256("ConfigUpdate(bytes32 imageHash,address[] wallets)")`
+
+### **6.3 Call Hashing**
+
+Individual calls are hashed using:
+
+```
+keccak256(
+ CALL_TYPEHASH,
+ to,
+ value,
+ keccak256(data),
+ gasLimit,
+ delegateCall,
+ onlyFallback,
+ behaviorOnError
+)
+```
+
+---
+
+## **7. Gas Optimization Features**
+
+### **7.1 Compact Encoding**
+
+The payload system uses several techniques to minimize gas costs:
+
+- **Flag-based encoding**: Single bytes control multiple parameters
+- **Variable-length fields**: Only encode necessary data
+- **Self-call optimization**: Avoid 20-byte address encoding for self-calls
+- **Conditional encoding**: Skip fields that have default values
+
+### **7.2 Batch Processing**
+
+Multiple calls can be executed in a single transaction, reducing:
+
+- Transaction overhead
+- Gas costs for multiple operations
+- Network congestion
+- User interaction requirements
+
+---
+
+## **8. Security Considerations**
+
+### **8.1 Replay Protection**
+
+- **Nonce system**: Each payload requires a unique nonce
+- **Space isolation**: Different nonce spaces prevent cross-contamination
+- **Chain ID binding**: Prevents cross-chain replay attacks
+
+### **8.2 Access Control**
+
+- **Signature validation**: All payloads require valid signatures
+- **Configuration binding**: Payloads are tied to specific wallet configurations
+- **Extension isolation**: Delegate calls are restricted to approved extensions
+
+### **8.3 Error Handling**
+
+- **Graceful degradation**: Failed calls don't necessarily fail the entire batch
+- **Gas protection**: Individual gas limits prevent infinite loops
+- **State consistency**: Error behaviors maintain wallet integrity
+
+---
+
+## **Conclusion**
+
+The Sequence payload system provides a powerful, gas-efficient mechanism for executing complex wallet operations. Through its compact binary encoding, flexible call structures, and comprehensive error handling, it enables wallets to perform sophisticated multi-step operations while maintaining security and efficiency.
+
+The system's integration with the broader Sequence ecosystem—including chained signatures, smart sessions, and configuration management—creates a cohesive framework for advanced wallet functionality. The payload system serves as the execution engine that brings together all these components into a unified user experience.
+
+This documentation serves as a technical reference for developers implementing and extending the payload system, providing both high-level architectural understanding and detailed implementation guidance.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/docs/SESSIONS.md b/lib/signals-implicit-mode/lib/sequence-v3/docs/SESSIONS.md
new file mode 100644
index 000000000..b764bd190
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/docs/SESSIONS.md
@@ -0,0 +1,502 @@
+# Ecosystem Wallets Smart Sessions Documentation
+
+This document provides an in-depth overview of the smart sessions system in Ecosystem wallets. It explains the encoding of signatures and configurations, details the permissions system, and distinguishes between explicit sessions and implicit sessions.
+
+---
+
+## Overview
+
+Ecosystem wallets smart sessions enable batched call authorization via signed payloads. Two primary session modes are supported:
+
+- **Explicit Sessions:**
+ Explicit sessions are part of the wallet's configuration. Their permissions are granted counter factually - derived from signature calldata. These permissions can be added or removed with a configuration update. As the configuration is tied to the wallet's image hash, any change to the wallet (and thus its image hash) immediately affects which explicit session permissions remain valid.
+
+- **Implicit Sessions:**
+ Implicit sessions are automatically able to sign on behalf of the wallet when they present an attestation that is signed by the wallet's identity signer. This mode leverages off-chain attestations and enforces additional constraints (e.g., blacklisting) to protect against misuse.
+
+---
+
+## Signature Encoding
+
+Signature encoding consists of **three** main parts:
+
+1. **Session Configuration Encoding**
+2. **Attestation List Encoding**
+3. **Call Signatures Encoding**
+
+Each part uses a specific layout and bit-level structure to efficiently encode the required data.
+
+---
+
+### 1. Session Configuration Encoding
+
+The session configuration is embedded within the signature as follows:
+
+```
+┌─────────────────────────────────────────────────────┐
+│ uint24 dataSize │
+│ ┌───────────────────────────────────────────────┐ │
+│ │ Session Configuration Bytes (dataSize bytes) │ │
+│ └───────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────┘
+```
+
+Within these configuration bytes, the data is structured as a series of tagged nodes. Each node begins with a flag byte that indicates the node type and any associated metadata.
+
+#### Flag Byte Structure
+
+```
+ ┌───────────────────────────────┐
+ │ Bits 7..4: FLAG │ (Identifies the node type)
+ │ Bits 3..0: Additional Data │ (Depends on the FLAG)
+ └───────────────────────────────┘
+```
+
+The following flags are defined:
+
+- **0x00: Permissions Node**
+- **0x01: Node (Pre-hashed 32-byte value)**
+- **0x02: Branch (Nested encoding)**
+- **0x03: Blacklist**
+- **0x04: Identity Signer**
+
+> [!IMPORTANT]
+> There must be exactly **one** Identity Signer and at most one Blacklist node. Multiple entries will trigger a validation error. If there are any implicit sessions (attestations), a blacklist is mandatory.
+
+#### Permissions Node (FLAG 0x00)
+
+This node encodes session permissions for a specific signer:
+
+```
+Permissions Node Layout:
+ ┌─────────────────────────────────────────────┐
+ │ Flag Byte │
+ │ ┌────────────────────────┐ │
+ │ │ Bits 7..4: FLAG (0x00) │ │
+ │ │ Bits 3..0: Unused │ │
+ │ └────────────────────────┘ │
+ │ Signer (address) │
+ │ Value Limit (uint256) │
+ │ Deadline (uint256) │
+ │ Permissions Array (encoded permissions) │
+ └─────────────────────────────────────────────┘
+```
+
+##### Permission Object Encoding
+
+Each permission object is structured as follows:
+
+```
+Permission Encoding:
+ ┌─────────────────────────────┐
+ │ Target Address │
+ │ Rules Count (uint8) │
+ │ ┌─────────────────────────┐ │
+ │ │ Parameter Rule 1 │ │
+ │ │ Parameter Rule 2 │ │ ... (if any)
+ │ └─────────────────────────┘ │
+ └─────────────────────────────┘
+```
+
+If the **Rules Count** is zero, the permission is considered _open_, allowing any call that targets the specified address without additional parameter restrictions.
+
+##### Parameter Rule Encoding
+
+Each parameter rule enforces conditions on the call data:
+
+```
+Parameter Rule Encoding:
+ ┌──────────────────────────────────────────────────────────────┐
+ │ Operation & Cumulative Flag (1 byte) │
+ │ ┌────────────────────────────────────────────────────────┐ │
+ │ │ Bits 7..1 (0xFE): Operation (e.g., 0 = EQUAL, etc.) │ │
+ │ │ Bit 0 (0x01): Cumulative flag (1 = cumulative) │ │
+ │ └────────────────────────────────────────────────────────┘ │
+ │ Value (bytes32) │
+ │ Offset (uint256) │
+ │ Mask (bytes32) │
+ └──────────────────────────────────────────────────────────────┘
+```
+
+> [!TIP]
+> A permission with an empty rules array is treated as _open_, granting unrestricted access to the target, subject only to other constraints such as value limits and deadlines.
+
+#### Node (FLAG 0x01)
+
+This node includes a 32-byte pre-hashed value:
+
+```
+Node Layout:
+ ┌──────────────────────────────┐
+ │ Flag Byte │
+ │ ┌────────────────────────┐ │
+ │ │ Bits 7..4: FLAG (0x01) │ │
+ │ │ Bits 3..0: Unused │ │
+ │ └────────────────────────┘ │
+ │ Node Hash (bytes32) │
+ └──────────────────────────────┘
+```
+
+This node is an optimization to reduce the size of the configuration tree in calldata. By using this node, unused permissions or configuration segments can be hidden, while still allowing the complete image hash to be derived.
+
+#### Branch (FLAG 0x02)
+
+Branches allow for the recursive grouping of nested configuration nodes into a single unit. They are used to bundle together multiple nodes - such as several permissions nodes or even other branch nodes - so that the entire collection can be processed as one entity. This design minimizes redundancy and optimizes the calldata size by avoiding repeated encoding of common structures.
+
+```
+Branch Node Layout:
+ ┌──────────────────────────────────────────────┐
+ │ Flag Byte │
+ │ ┌────────────────────────────────────────┐ │
+ │ │ Bits 7..4: FLAG (0x02) │ │
+ │ │ Bits 3..0: Size of size field in bytes │ │
+ │ └────────────────────────────────────────┘ │
+ │ Size (uintX, where X is determined above) │
+ │ Branch Data (nested configuration bytes) │
+ └──────────────────────────────────────────────┘
+```
+
+The **Size** field specifies the total number of bytes that the branch occupies. The size of this field is determined by the additional data portion of the flag byte (bits 3..0), which indicates how many bytes are used to encode the size. The branch data that follows can include a mix of permissions nodes, pre-hashed nodes, blacklists, and even other branches. When processing a branch:
+
+- The branch data is parsed recursively, with each nested node being processed according to its own flag.
+- The leaf hashes of all nested nodes are computed.
+- These individual hashes are then combined (e.g., using `LibOptim.fkeccak256`) to produce a single cumulative hash representing the entire branch.
+- This branch hash is then integrated into the parent configuration's image hash, ensuring that all the nested information contributes to the final cryptographic fingerprint.
+
+> [!TIP]
+> Branch nodes are especially useful for modularizing the configuration structure. They allow logically related nodes to be grouped together, which not only improves organization but also potentially reduces the overall size of the calldata by allowing unused leaves to be rolled up into a single node.
+
+#### Blacklist (FLAG 0x03)
+
+The blacklist node specifies addresses that are disallowed for implicit sessions. This includes both target addresses that cannot be called and session signers that are not allowed to make implicit calls.
+
+```
+Blacklist Node Layout:
+ ┌──────────────────────────────────────────────┐
+ │ Flag Byte │
+ │ ┌────────────────────────────────────────┐ │
+ │ │ Bits 7..4: FLAG (0x03) │ │
+ │ │ Bits 3..0: Blacklist count or 0x0F │ │
+ │ └────────────────────────────────────────┘ │
+ │ [Optional] Extended Count (uint16) │
+ │ Blacklisted Addresses (sorted array) │
+ └──────────────────────────────────────────────┘
+```
+
+The blacklist count is encoded in the additional data portion of the flag byte (bits 3..0):
+
+- If the count is 14 or less, it is stored directly in these bits
+- If the count is 15 or more, these bits are set to 0x0F and the actual count is stored in the next 2 bytes as a uint16
+
+The blacklist serves two security purposes:
+
+1. Prevents implicit sessions from calling specific target addresses
+2. Blocks specific session signers from making any implicit calls
+
+When an implicit session call is made, both the session signer and the target address are checked against the blacklist. If either appears in the blacklist, the call will be rejected with a `BlacklistedAddress` error.
+
+> [!IMPORTANT]
+> For implicit sessions, the blacklist is mandatory. The blacklist addresses must be sorted or validation will fail. This is to allow a binary search during validation.
+
+> [!WARNING]
+> The blacklist doesn't not prevent explicit sessions from calling blacklisted addresses or prevent explicit signers. To block an explicit session or it's permissions, update the wallet configuration to remove the explicit session.
+
+#### Identity Signer (FLAG 0x04)
+
+Specifies the identity signer used for attestation verification:
+
+```
+Identity Signer Layout:
+ ┌──────────────────────────────┐
+ │ Flag Byte │
+ │ ┌────────────────────────┐ │
+ │ │ Bits 7..4: FLAG (0x04) │ │
+ │ │ Bits 3..0: Unused │ │
+ │ └────────────────────────┘ │
+ │ Identity Signer (address) │
+ └──────────────────────────────┘
+```
+
+> [!IMPORTANT]
+> The configuration must include exactly one identity signer. Duplicate or missing entries trigger an error.
+
+---
+
+### 2. Attestation List Encoding
+
+After reading the session configuration, a single byte `attestationCount` indicates how many attestations follow:
+
+```
+┌─────────────────────────────────────────────────────┐
+│ uint8 attestationCount │
+│ ┌────────────────────────────────────────────────┐ │
+│ │ Attestation + identity signature │ │
+│ │ ... repeated attestationCount times ... │ │
+│ └────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────┘
+```
+
+Each attestation is encoded as described in [Attestation (Implicit Sessions)](#attestation-implicit-sessions) below, then followed by a single identity signature from the configured identity signer (in EIP-2098 compact form).
+
+If `attestationCount > 0` but no blacklist node was present in the configuration, validation fails.
+
+---
+
+### 3. Call Signatures Encoding
+
+Each call in the payload is accompanied by a call signature. The encoding differs slightly for explicit sessions and implicit sessions.
+
+#### Call Signature Structure
+
+```
+Call Signature Layout:
+ ┌─────────────────────────────────────────────────────────────┐
+ │ Flag Byte │
+ │ ┌────────────────────────────────────────────────────────┐│
+ │ │ Bit 7 (0x80): isImplicit flag ││
+ │ │ Bits 6..0 (0x7F): If implicit, this is the attestation ││
+ │ │ index; if explicit, this is the ││
+ │ │ session permission index ││
+ │ └────────────────────────────────────────────────────────┘│
+ │ Session Signature (EIP-2098 compact: see below) │
+ └─────────────────────────────────────────────────────────────┘
+```
+
+> [!IMPORTANT]
+> The flag byte is critical for distinguishing call types. For implicit sessions, the most significant bit (Bit 7) must be set. For explicit sessions, the lower 7 bits represent the permission index.
+
+The session signature is an ECDSA signature of the call and replay protection information in the payload (nonce, space and chainId).
+
+No attestation data is embedded here for implicit calls; instead, each implicit call references an attestation by index from the Attestation List.
+
+#### EIP-2098 Compact Signature Encoding
+
+Compact signatures follows the [EIP-2098](https://eip.tools/eip/2098) compact signature format. In this format, the signature is encoded as follows:
+
+```
+EIP-2098 Compact Encoding:
+ ┌─────────────────────────────────────────────────────────────┐
+ │ 256-bit r value │
+ │ 1-bit yParity (encoded into s) │
+ │ 255-bit s value │
+ └─────────────────────────────────────────────────────────────┘
+```
+
+This encoding merges the `v` value into the `s` value, reducing the overall signature size while maintaining full signature recovery capability.
+
+---
+
+## Permissions System
+
+The permissions system governs what actions a session signer is allowed to execute within explicit sessions. It is designed to be flexible, allowing validations on any field within the call data through the use of **value**, **offset**, and **mask** parameters.
+
+### Session Permissions (Explicit Sessions)
+
+Defined in the `SessionPermissions` struct, these include:
+
+- **Signer:** Authorized session signer.
+- **Value Limit:** Maximum native token value allowed.
+- **Deadline:** Expiration timestamp (0 indicates no deadline).
+- **Permissions Array:** List of permission objects.
+
+> [!WARNING]
+> If a session's deadline is set and the current block timestamp exceeds it, the session is considered expired and all calls will be rejected.
+
+### Permission Object and Parameter Rules
+
+Each permission object specifies a target contract and a set of rules that define acceptable call parameters.
+
+#### Permission Object Recap
+
+```
+Permission Object:
+ ┌────────────────────────────────┐
+ │ Target Address │
+ │ Rules Count (uint8) │
+ │ Rules (array of ParameterRule) │
+ └────────────────────────────────┘
+```
+
+#### Parameter Rule Recap
+
+```
+Parameter Rule:
+ ┌────────────────────────────────────────────────────────────┐
+ │ Operation & Cumulative Flag (1 byte) │
+ │ ┌──────────────────────────────────────────────────────┐ │
+ │ │ Bits 7..1 (0xFE): Operation (e.g., 0 = EQUAL, etc.) │ │
+ │ │ Bit 0 (0x01): Cumulative flag (1 = cumulative) │ │
+ │ └──────────────────────────────────────────────────────┘ │
+ │ Value (bytes32) │
+ │ Offset (uint256) │
+ │ Mask (bytes32) │
+ └────────────────────────────────────────────────────────────┘
+```
+
+> [!TIP]
+> A permission with an empty rules array is treated as _open_, granting unrestricted access to the target, subject only to other constraints such as value limits and deadlines.
+
+---
+
+## Detailed Permission Rules and Validation
+
+The permission rules mechanism provides a powerful and flexible method to validate any field within the call data. Here's a detailed look at how the rules work:
+
+### Components of a Permission Rule
+
+- **Value:**
+ The expected value (stored as a `bytes32`) used for comparison.
+
+- **Offset:**
+ The byte offset in the call data from which the 32-byte parameter is extracted.
+
+- **Mask:**
+ A bitmask applied to the extracted data. This isolates the relevant bits, allowing validation even when the field is embedded within a larger data structure.
+
+### Validation Process
+
+For each rule, the validation function performs the following steps:
+
+1. **Extraction:**
+ Read 32 bytes from the call data starting at the specified offset:
+
+ ```solidity
+ bytes32 extracted_value = call.data.readBytes32(rule.offset);
+ ```
+
+2. **Masking:**
+ Apply the mask to isolate the target bits:
+
+ ```solidity
+ bytes32 masked_value = extracted_value & rule.mask;
+ ```
+
+3. **Comparison:**
+ Compare the masked value with the expected value using the defined operation:
+ - **EQUAL:** The masked value must exactly equal the expected value.
+ - **LESS_THAN_OR_EQUAL:** The masked value must be less than or equal to the expected value.
+ - **GREATER_THAN_OR_EQUAL:** The masked value must be greater than or equal to the expected value.
+ - **NOT_EQUAL:** The masked value must not equal the expected value.
+
+> [!TIP]
+> This approach allows validation on any field within the call data regardless of its format or position.
+
+### The Cumulative Flag
+
+When the **cumulative** flag is set on a permission rule:
+
+1. **Cumulative Calculation:**
+ The value extracted from the current call is added to a previously recorded usage amount (stored in the payload's usage limits or persistent storage).
+
+2. **Threshold Comparison:**
+ The cumulative total (current value plus previous usage) is compared against the threshold defined by the rule.
+
+3. **Preceding Update:**
+ Because cumulative values persist across multiple calls, a preceding call to `incrementUsageLimit` is required. This call updates the on-chain storage with the new cumulative total, ensuring that future validations reflect the updated usage.
+
+> [!WARNING]
+> Cumulative usage is tracked using hashes: `keccak256(abi.encode(signer, permission, ruleIdx))` for rules and `keccak256(abi.encode(signer, VALUE_TRACKING_ADDRESS))` for native tokens. Modifying a permission creates a new hash, so the old usage state must be considered when modifying a permission.
+
+### Example: ERC20.transfer
+
+Consider an ERC20 token `transfer` function:
+
+```solidity
+function transfer(address to, uint256 amount) returns (bool);
+```
+
+**Call Data Layout:**
+
+- **4 bytes:** Function selector.
+- **32 bytes:** Encoded `to` address.
+- **32 bytes:** Encoded `amount`.
+
+**Permission Rule Setup:**
+
+- **Target:**
+ The ERC20 token contract address.
+
+- **Offset:**
+ `36` bytes (4 bytes for the function selector + 32 bytes for the `to` address) - this is where the `amount` parameter begins.
+
+- **Mask:**
+ A full mask (`0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF`) to extract the entire 32-byte value.
+
+- **Value:**
+ `100 * 10^18` (expressed as a `bytes32` value) to represent a maximum transfer amount of 100 tokens (assuming 18 decimals).
+
+- **Operation:**
+ `LESS_THAN_OR_EQUAL` - ensuring the transfer amount does not exceed the threshold.
+
+- **Cumulative Flag (optional):**
+ If you want to enforce a cumulative limit (e.g., a daily cap), set the cumulative flag. Each transfer's amount is then added to a cumulative total that must not exceed the threshold, with an `incrementUsageLimit` call required to update the stored value.
+
+> [!NOTE]
+> ERC20.transfer Example Recap: The permission rule extracts the `amount` parameter from call data at offset 36, applies a mask to isolate the full value, and verifies that the value is less than or equal to 100 \* 10^18. Optionally, if the cumulative flag is set, it enforces a cumulative limit across multiple calls. In practice, the permission would also include a rule to check the function selector, ensuring that the call is to the `transfer` function.
+
+---
+
+## Attestation (Implicit Sessions)
+
+Implicit sessions use an attestation to verify that the session signer is approved. The attestation is encoded and then validated by the target contract.
+
+### Attestation Encoding
+
+```
+Attestation Encoding:
+ ┌──────────────────────────────────────────────┐
+ │ Approved Signer (address) │
+ │ Identity Type (bytes4) │
+ │ Issuer Hash (bytes32) │
+ │ Audience Hash (bytes32) │
+ │ Application Data Length (uint24) │
+ │ Application Data (variable bytes) │
+ │ Redirect URL Length (uint24) │
+ │ Redirect URL (variable string) │
+ │ Issued At (uint64) │
+ └──────────────────────────────────────────────┘
+```
+
+The Attestation data obtained during authentication. The `Identity Type` is the type of identity that was used to authenticate the user. The `Issuer Hash` is the hash of the issuer. The `Audience Hash` is the hash of the audience. The `Application Data` can be provided by the dapp. The `Auth Data` contains the redirect URL (string) and issuance timestamp (uint64).
+
+> [!WARNING]
+> The `Application Data` length is encoded using a `uint24`. Ensure that data lengths are within these limits.
+
+> [!NOTE]
+> The `Redirect URL` length is encoded using a `uint24`, and the `Issued At` field is a `uint64` timestamp representing when the attestation was issued. The encoding order is: `redirectUrlLength` (uint24), `redirectUrl` (string), `issuedAt` (uint64).
+
+### Attestation Validation
+
+- The attestation's **approved signer** must match the session signer.
+- A magic value is generated using a combination of a prefix, the wallet address, the attestation's audience hash, and issuer hash.
+- The attestation signature is validated against the identity signer from the configuration.
+- The target contract's `acceptImplicitRequest` function must return the expected magic value; otherwise, the call is rejected.
+
+> [!WARNING]
+> Implicit sessions require a properly encoded blacklist in the configuration. Calls to a blacklisted address will be rejected, and missing blacklist data will cause validation errors.
+
+---
+
+## Future Improvements
+
+Several improvements can be made
+
+> [!NOTE]
+> Configuration Flexibility: Introduce versioning or additional flags in the configuration encoding to support new features while preserving backward compatibility. Allow dynamic adjustments without breaking the merkle tree-based image hash structure.
+
+> [!NOTE]
+> Gas Optimization: Optimize the recursive encoding/decoding logic for configurations with a large number of permissions or deep branch nesting to reduce gas costs.
+
+> [!NOTE]
+> Call Signature Optimization: Optimize the call signature encoding to reduce the size of the calldata. A potential target for optimization is to remove repeated encodings of the same attestation data.
+
+> [!NOTE]
+> Advanced Permission Rules: Extend the permission system to support more complex conditional checks or dynamic rule adjustments. Provide improved error messages and diagnostic tools for failed validations.
+
+---
+
+## Conclusion
+
+The smart sessions system in Ecosystem wallets offers a flexible framework for authorizing batched operations via signed payloads. By leveraging detailed encoding schemes for configuration, permissions, and attestations - and by deriving an image hash that cryptographically fingerprints the configuration tree (even when sparse) - the system supports both explicit sessions and implicit sessions while ensuring robust validation. The detailed permission rules, including the use of **value**, **offset**, and **mask**, provide granular control over call data validation, and the cumulative flag facilitates persistent limits across calls. The outlined future improvements aim to enhance security, efficiency, and usability as the system evolves.
+
+This documentation serves as a technical guide for developers integrating and extending the smart sessions framework, providing both detailed encoding breakdowns and practical considerations for deployment and further development.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/docs/SIGNATURE.md b/lib/signals-implicit-mode/lib/sequence-v3/docs/SIGNATURE.md
new file mode 100644
index 000000000..38d1fb695
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/docs/SIGNATURE.md
@@ -0,0 +1,367 @@
+# **Technical Document: Sequence Signature Encoding**
+
+This document describes, in detail, how the Sequence signature encoding is structured, how each part is packed into bytes, and how chained signatures and top-level signatures work. It is purely technical, explaining the bit layouts, flags, and usage with examples.
+
+---
+
+## **1. Overview**
+
+Sequence uses a specialized signature format that:
+
+1. Has a **top-level signature** that includes:
+ - A single "signature flag" byte that encodes multiple fields (checkpointer usage, signature type, checkpoint size, threshold size, etc.).
+ - (Optionally) data related to an on-chain checkpointer contract.
+ - A notion of _chained signatures_ vs. _normal signatures_ vs. _“no chain id”_ signatures.
+ - A final threshold and checkpoint value that tie into the overall wallet or contract logic.
+
+2. Contains a **merkle-like structure** for the signers at the “branch” level, where each “leaf” or “node” is encoded using a separate mini-flag nibble. This is parsed with a loop in the `recoverBranch` function.
+
+3. Supports multiple sub-signature types, such as ECDSA (`FLAG_SIGNATURE_HASH` or `FLAG_SIGNATURE_ETH_SIGN`), ERC-1271 contract-based checks, nested “multi-sig inside multi-sig,” and special “sapient” signatures. Each sub-signature or branch piece is prefixed by one byte: the top nibble is the “flag type” and the bottom nibble contains per-flag configuration bits (like weight, sizes, or additional bits for `v`).
+
+---
+
+## **2. Top-level Signature Format**
+
+When `recover` is first invoked, it reads the **first byte** of the signature as `signatureFlag`. That byte is bit-packed as follows (with bit `0` as the least-significant bit):
+
+```
+ ┌─────────────── Bit 7 (0x80) : Static signature
+ │ ┌───────────── Bit 6 (0x40) : Checkpointer usage flag
+ │ │ ┌─────────── Bit 5 (0x20) : Threshold size indicator (0 => 1 byte, 1 => 2 bytes)
+ │ │ │ ┌──────── Bits 4..2 (0x1C) : Checkpoint size (encoded as an integer 0..7)
+ │ │ │ │ ┌───── Bit 1 (0x02) : "no chain id" signature type
+ │ │ │ │ │ ┌─── Bit 0 (0x01) : "chained" signature type
+[7 6 5 432 1 0]
+```
+
+We can break this down more concretely:
+
+1. **Bit 7** set (`0x80`) indicates a static signature:
+ - When set, the signature has been pre-stored in contract storage and bypasses normal validation
+ - Validation only checks:
+ - That the stored expiry timestamp has not passed
+ - That the stored signer matches the transaction sender (or is unset with `address(0)`)
+1. **Bit 6** set (`0x40`) means the signature includes an external **imageHash checkpointer**:
+ - If set, the signature will contain:
+ - The checkpointer contract `address`
+ - A 3-byte length for the “checkpointer data”
+ - That data, passed to `ICheckpointer(checkpointer).snapshotFor(...)`
+1. **Bits 4..2** (the field `((signatureFlag & 0x1c) >> 2)`) define the **checkpoint size** in bytes. Possible values are `0..7`. If this value is `N`, then the next `N` bytes of the signature after reading the flag (and optional checkpointer data) represent the **checkpoint**.
+1. **Bit 5** (`0x20`) sets how many bytes are used to read the threshold. If it is `0`, the threshold is read as 1 byte; if it is `1`, the threshold is read as 2 bytes. (Hence `( (signatureFlag & 0x20) >> 5 ) + 1`.)
+1. **Bit 1** (`0x02`) indicates the “no chain id” signature. If set, `_payload.noChainId` is true. This affects how `_payload.hash()` is computed.
+1. **Bit 0** (`0x01`) indicates the signature is **chained**. In that case, the code calls `recoverChained`, which processes multiple sub-signatures in sequence.
+
+Putting it together:
+
+- If bit `0` is set, we do a **chained** approach: The signature is composed of chunks, each chunk specifying a length and then a nested signature.
+- Otherwise, we do a “regular” top-level parse: we read the checkpoint size, threshold size, then parse the “branch” for signers.
+
+### **Example of a Top-level Signature Byte**
+
+Suppose the top-level `signatureFlag` is `0x74` in hex. Converting `0x74` to binary:
+
+```
+0x74 = 01110100 in binary
+ ^ ^ ^ ^
+bit 7: 0 (reserved)
+bit 6: 1 => checkpointer usage
+bit 5: 1 => threshold uses 2 bytes
+bits 4..2: 101 => checkpoint size = 5 bytes
+bit 1: 0 => normal (not "no chain id")
+bit 0: 0 => not chained
+```
+
+From this:
+
+- We first read an `address` for the checkpointer, then read 3 bytes for the checkpointer data length, etc.
+- We know we must parse **5 bytes** for the checkpoint value.
+- Then parse **2 bytes** for the threshold.
+- Then parse the remainder as the merkle-branch structure for signers.
+
+---
+
+## **3. Chained Signatures**
+
+When **bit 0** is set (the least-significant bit), the signature is **chained**. Instead of the usual approach (parsing threshold, checkpoint, etc. from that same byte), the code calls:
+
+```solidity
+recoverChained(_payload, snapshot, _signature);
+```
+
+A chained signature is a series of **signature chunks**, each chunk defined like this:
+
+```
+[3-byte length] [chunk of that length]
+[3-byte length] [chunk of that length]
+...
+```
+
+Each chunk can itself be a top-level signature in the sense that it calls `recover(...)` again—except it ignores checkpointer details after the first chunk. The code enforces:
+
+- Each chunk recovers `(threshold, weight, imageHash, checkpoint)`.
+- If `weight < threshold`, it reverts with `LowWeightChainedSignature`.
+- The `checkpoint` must be **strictly less** than the previous chunk’s `checkpoint`, ensuring correct ordering (`WrongChainedCheckpointOrder`).
+- All but the first chunk are interpreted as a “configuration update” with a special “linkedPayload.”
+
+This allows multiple signature instructions to be “chained” in a single byte array.
+
+```
+ 0 1 2 3
+ |----- byte indices: 0..2 => 3-byte length L1
+ |----- next L1 bytes => chunk #1
+ ...
+ |----- next 3 bytes => length L2
+ |----- next L2 bytes => chunk #2
+ ...
+ |----- next 3 bytes => length L3
+ |----- next L3 bytes => chunk #3
+ ...
+
+```
+
+Each chunk is itself a “top-level style signature” minus the repeated checkpointer usage. The final `(threshold, weight, imageHash, checkpoint)` from the last chunk can be used to validate the overall signature.
+
+---
+
+## **4. Branch-Level Parsing**
+
+Regardless of whether it is a chained signature or a direct one, eventually the code calls:
+
+```solidity
+recoverBranch(_payload, opHash, _signature)
+```
+
+This function loops over the remainder of the signature, reading one byte at a time as the “header” for a sub-signature or branch item. We’ll call that one byte `firstByte`. The code extracts:
+
+- `flag = (firstByte & 0xf0) >> 4;` (the top nibble)
+- The lower nibble is used as “free bits.”
+
+### **4.1 Flag Values**
+
+The contract defines constants:
+
+| Constant Name | Value (Decimal) | Purpose |
+| -------------------------------------- | --------------- | ----------------------------------------------------------------------------------------------------- |
+| `FLAG_SIGNATURE_HASH` | 0 | ECDSA signature with `r,yParityAndS` (ERC-2098 compact) directly against `_opHash`. |
+| `FLAG_ADDRESS` | 1 | Just an address “leaf” (with no actual ECDSA check) |
+| `FLAG_SIGNATURE_ERC1271` | 2 | A contract-based signature check using `isValidSignature(opHash, signature)` |
+| `FLAG_NODE` | 3 | Includes a raw 32-byte node hash in the merkle root. No weight added. |
+| `FLAG_BRANCH` | 4 | Nested branch. The next bytes specify length, then recursion into `recoverBranch`. |
+| `FLAG_SUBDIGEST` | 5 | Hard-coded “accepted subdigest.” If `_opHash` matches the stored 32 bytes, infinite weight. |
+| `FLAG_NESTED` | 6 | A nested multi-sig node with an internal threshold plus an external weight. |
+| `FLAG_SIGNATURE_ETH_SIGN` | 7 | ECDSA signature in “Eth_sign” format (`"\x19Ethereum Signed Message:\n32" + opHash`), using ERC-2098. |
+| `FLAG_SIGNATURE_ANY_ADDRESS_SUBDIGEST` | 8 | `FLAG_SUBDIGEST` but with counter factual support. |
+| `FLAG_SIGNATURE_SAPIENT` | 9 | A specialized “sapient” signature with an `ISapient` contract check. |
+| `FLAG_SIGNATURE_SAPIENT_COMPACT` | 10 | A specialized “sapient” signature with `ISapientCompact` and `_opHash` only. |
+
+When the parser sees `flag == someValue`, it dispatches to the corresponding block. Each block interprets the lower nibble differently.
+
+---
+
+## **5. Detailed Flag-by-Flag Format**
+
+Below are the internal mini-formats for each **flag**. Recall that in code, `firstByte` is the single byte at the start of each item, and we do:
+
+```
+flag = (firstByte & 0xf0) >> 4; // top nibble
+// "free nibble" = (firstByte & 0x0f)
+```
+
+Each bullet will show how the bits in the “free nibble” are used.
+
+---
+
+### 5.1 **Signature Hash** (`flag = 0`)
+
+- Uses **ERC-2098** to parse the signature in 64 bytes (`r` + `yParityAndS`).
+- The free nibble bits [3..0] define the signer's weight (0 => we read the weight from the next byte, else 1..15).
+- After reading `r` (32 bytes) and `yParityAndS` (32 bytes), the top bit of `yParityAndS` (bit 255) is `yParity` (0 or 1), which is added to 27 to form `v`. The remaining 255 bits are `s`.
+- We then perform `ecrecover(_opHash, v, r, s)`.
+
+**Example**
+If the sub-signature byte is `0x05` (`0000 0101` in binary), then top nibble=0 => `FLAG_SIGNATURE_HASH`, free nibble=5 => weight=5. We do **not** read an extra byte for the weight. Next, we read 64 bytes as the compact signature: 32 bytes for `r`, 32 bytes for `yParityAndS`. If the top bit of `yParityAndS` is 0 => `v=27`; if it is 1 => `v=28`. The rest is `s`. Then we do `ecrecover`.
+
+---
+
+### 5.2 **Address** (`flag = 1`)
+
+- Takes an address leaf (no ECDSA).
+- The free nibble bits 3..0 define the weight in the same scheme:
+ - If those bits are zero, read an extra byte for weight.
+ - Else use that 1..15 as the weight.
+- Then reads 20 bytes for the address.
+- Merges `_leafForAddressAndWeight(addr, weight)`.
+
+---
+
+### 5.3 **Signature ERC-1271** (`flag = 2`)
+
+- The free nibble bits are used as:
+ - The bottom two bits are the weight (with the same “0 => dynamic read, else 1..3” logic).
+ - The next two bits define the size of the “signature size” field: 0..3 means we read 0..3 bytes to get the dynamic length of the next part.
+- Then we read 20 bytes for the contract address, read that dynamic-size signature, and call `IERC1271(addr).isValidSignature(_opHash, data)`. If it returns the magic value `0x1626ba7e`, it is valid; otherwise revert.
+- Weight is added if valid.
+
+**Example**
+
+```
+firstByte = 0x2D -> 0010 1101 in binary
+ top nibble = 2 -> FLAG_SIGNATURE_ERC1271
+ free nibble = 0xD = 1101 in binary
+ bits 3..2 = 11 -> sizeSize=3 => read 3 bytes to get length
+ bits 1..0 = 01 -> weight=1
+```
+
+Then parse next 3 bytes to discover how big the signature is, read it, do the 1271 check.
+
+---
+
+### 5.4 **Node** (`flag = 3`)
+
+- No free bits used.
+- Simply reads a 32-byte “node hash” and merges it.
+- No weight is added.
+
+---
+
+### 5.5 **Branch** (`flag = 4`)
+
+- The free nibble bits 3..0 define how many bytes are used to read the upcoming “branch size.”
+- Once the branch size is read, we extract that many bytes as a sub-branch, and recursively call `recoverBranch` on that sub-slice.
+- We get `(nweight, nodeHash)` from that sub-branch, add `nweight` to the total, and merge the nodeHash into the root.
+
+---
+
+### 5.6 **Subdigest** (`flag = 5`)
+
+- The code reads a 32-byte “hardcoded subdigest.” If it matches the `_opHash`, sets `weight = type(uint256).max`.
+- Merges `_leafForHardcodedSubdigest(hardcoded)`.
+
+This effectively means “if the 32 bytes match the current operation hash, we grant infinite weight.”
+
+---
+
+### 5.7 **Nested** (`flag = 6`)
+
+- The free nibble is split:
+ - The bottom two bits define the “external weight.” Again, `0 => read from next byte, else 1..3`.
+ - The next two bits define the “internal threshold” size. If `0`, read 2 bytes from the next portion for that threshold, else 1..3 is just 1..3?
+ - Then read 3 bytes to get the length of the nested sub-branch, parse it. That yields `(internalWeight, internalRoot)`.
+ - If `internalWeight >= internalThreshold`, we add the external weight to the total. Finally, we merge `_leafForNested(internalRoot, internalThreshold, externalWeight)` into the root.
+
+**Example**
+
+```
+firstByte = 0x64 -> 0110 0100 in binary
+ top nibble = 6 -> FLAG_NESTED
+ free nibble = 0x4 = 0100 in binary
+ bits 3..2 = 01 -> internalThreshold=1
+ bits 1..0 = 00 -> externalWeight => read from next byte
+```
+
+Then read next byte for externalWeight, read next 2 bytes for threshold if needed, etc.
+
+---
+
+### 5.8 **Signature ETH Sign** (`flag = 7`)
+
+- Similar to `FLAG_SIGNATURE_HASH`, but recovers via:
+
+```
+ecrecover( keccak256("\x19Ethereum Signed Message:\n32" + _opHash), v, r, s )
+```
+
+- Uses **ERC-2098**: we read 64 bytes (32 for `r`, 32 for `yParityAndS`), retrieve `yParity` from the top bit, add 27 to form `v`, and use the remainder as `s`.
+- The free nibble bits [3..0] define the weight (0 => dynamic read, else 1..15).
+
+---
+
+### 5.9 **Signature Any Address Subgiest** (`flag = 8`)
+
+- The code reads a 32-byte "hardcoded subdigest." If it matches `_payload.hashFor(address(0))`, sets `weight = type(uint256).max`.
+- Merges `_leafForAnyAddressSubdigest(anyAddressOpHash)`.
+
+This effectively means "if the 32 bytes match the operation hash computed for address(0), we grant infinite weight." This allows for counter-factual payloads.
+
+---
+
+### 5.10 **Signature Sapient** (`flag = 9`)
+
+- The free nibble is structured like `ERC1271`: some bits define how many bytes to read for the signature, some bits define the weight.
+- Then it calls `ISapient(addr).recoverSapientSignature(_payload, data)`, which must return a “sapientImageHash” used in `_leafForSapient`.
+- Weight is added if valid.
+
+---
+
+### 5.11 **Signature Sapient Compact** (`flag = 10`)
+
+- Same approach as `FLAG_SIGNATURE_SAPIENT`, except the contract uses `ISapientCompact.recoverSapientSignatureCompact(_opHash, data)` instead, passing only `_opHash`.
+
+---
+
+## **6. Merkle Root Construction**
+
+The branch parser accumulates a “root” by repeatedly combining leaves with the function:
+
+```solidity
+root = LibOptim.fkeccak256(root, leaf)
+```
+
+In each sub-flag block, a leaf is computed, for example:
+
+- `_leafForAddressAndWeight(address, weight)`
+- `_leafForNested(internalRoot, threshold, externalWeight)`
+- `_leafForHardcodedSubdigest(someDigest)`
+- etc.
+
+The final `root` is combined with the threshold and checkpoint (and checkpointer address, if present) to yield the final “imageHash.” That is used to tie the signatures to a specific configuration or permission set.
+
+---
+
+## **7. Example Putting it All Together**
+
+Below is a hypothetical top-level signature that is **not** chained, uses a checkpointer, has a 2-byte threshold, a 1-byte checkpoint, and then includes a single ECDSA leaf:
+
+1. **signatureFlag** = `0x6C` => in binary `0110 1100`
+ - Bit 6 => `1`, so we have a checkpointer
+ - Bit 5 => `1`, threshold uses 2 bytes
+ - Bits 4..2 => `110` => checkpoint size = 6 bytes
+ - Bit 1 => `0`, normal chain id usage
+ - Bit 0 => `0`, not chained
+2. We read:
+ - `checkpointer` address (20 bytes)
+ - 3-byte checkpointer data size => parse that data
+ - 6 bytes => the “checkpoint” number
+ - 2 bytes => the threshold
+3. We jump into `recoverBranch`, and the next 1-byte might be `0x02` in hex => top nibble=0 => `FLAG_SIGNATURE_HASH` with free nibble=2 => weight=2. Then parse 64 bytes for ERC-2098. We derive `v` from the top bit of the second 32 bytes, do ecrecover, and merge the address in the merkle root.
+
+Finally, the code compares the final computed image hash, checks if we pass threshold vs. weight, checks snapshot logic, and returns `(threshold, weight, imageHash, checkpoint)`.
+
+---
+
+## **8. Snapshot and Checkpointer Logic**
+
+If the top-level byte indicates we have a checkpointer (`bit 6` set), we read:
+
+- The checkpointer’s address
+- The next 3 bytes => `checkpointerDataSize`
+- That many bytes => `checkpointerData`
+
+We call:
+
+```solidity
+snapshot = ICheckpointer(checkpointer).snapshotFor(address(this), checkpointerData);
+```
+
+This yields a `Snapshot { imageHash, checkpoint }`. If the final signature’s computed `imageHash` and `checkpoint` do not properly exceed or match the snapshot, the code can revert with `UnusedSnapshot`.
+
+---
+
+## **9. Summary**
+
+1. **Top-level “signatureFlag”** byte sets the “checkpointer usage,” “signature type,” “checkpoint size,” “threshold size,” etc.
+2. If the signature is **chained**, parse a series of sub-signatures, each of which in turn calls the normal `recover`.
+3. Eventually, a **branch** parse is done with `recoverBranch`, which looks at many items. Each item is marked by a single byte whose **top nibble** identifies the flag (ECDSA, ERC1271, sub-branch, nested multi-sig, etc.), and whose **bottom nibble** has special bits (like the signers’ weight, or signature-size format).
+4. The final output is `(threshold, weight, imageHash, checkpoint)` plus snapshot checks if any.
+
+This structure allows advanced multi-signature logic, nested multi-sigs, infinite weight if a known subdigest matches `_opHash`, and optional checkpointer extension.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/foundry.toml b/lib/signals-implicit-mode/lib/sequence-v3/foundry.toml
new file mode 100644
index 000000000..bd0622cc1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/foundry.toml
@@ -0,0 +1,31 @@
+[profile.default]
+src = "src"
+out = "out"
+libs = ["lib"]
+via-ir = true
+optimizer = true
+optimizer_runs = 4294967295
+fs_permissions = [{ access = "read-write", path = "/tmp"}]
+solc = "0.8.28"
+evm_version = "paris"
+remappings = [
+ "account-abstraction/=lib/account-abstraction/contracts/"
+]
+
+[fuzz]
+max_test_rejects = 1000000
+
+[fmt]
+# Explicitly define all formatting rules
+multiline_func_header = "params_first"
+single_line_statement_blocks = "multi"
+sort_imports = true
+contract_new_lines = true
+override_spacing = false
+line_length = 120
+tab_width = 2
+bracket_spacing = true
+int_types = "long"
+quote_style = "double"
+hex_underscore = "remove"
+wrap_comments = false
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lefthook.yml b/lib/signals-implicit-mode/lib/sequence-v3/lefthook.yml
new file mode 100644
index 000000000..6adffd9a5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lefthook.yml
@@ -0,0 +1,8 @@
+pre-commit:
+ commands:
+ forge-fmt:
+ glob: '**/*.sol'
+ run: forge fmt {staged_files} && git add {staged_files}
+ prettier:
+ glob: '**/*.{js,jsx,ts,tsx,json,md,yml,yaml}'
+ run: pnpm prettier --write {staged_files} && git add {staged_files}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.eslintrc.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.eslintrc.js
new file mode 100644
index 000000000..fde1d6d69
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.eslintrc.js
@@ -0,0 +1,79 @@
+module.exports = {
+ env: {
+ browser: true,
+ es6: true,
+ jest: true,
+ mocha: true,
+ node: true
+ },
+ globals: {
+ artifacts: false,
+ assert: false,
+ contract: false,
+ web3: false
+ },
+ extends:
+ [
+ 'standard-with-typescript'
+ ],
+ // This is needed to add configuration to rules with type information
+ parser: '@typescript-eslint/parser',
+ parserOptions: {
+ project: ['./tsconfig.json']
+ },
+ ignorePatterns: [
+ '.eslintrc.js',
+ '**/types/truffle-contracts',
+ 'coverage',
+ 'dist/'
+ ],
+ rules: {
+ 'no-console': 'off',
+ '@typescript-eslint/no-var-requires': 'off',
+ '@typescript-eslint/return-await': 'off',
+ '@typescript-eslint/no-unnecessary-type-assertion': 'off',
+ '@typescript-eslint/require-array-sort-compare': ['error',
+ {
+ ignoreStringArrays: true
+ }
+ ]
+ },
+ overrides: [
+ {
+ files: '*',
+ rules: {
+ '@typescript-eslint/naming-convention': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/restrict-template-expressions': 'off'
+ }
+ },
+ {
+ files: [
+ '**/test/**/*.ts'
+ ],
+ rules: {
+ 'no-unused-expressions': 'off',
+ // chai assertions trigger this rule
+ '@typescript-eslint/no-unused-expressions': 'off',
+ '@typescript-eslint/no-non-null-assertion': 'off'
+ }
+ },
+ {
+ // otherwise it will raise an error in every JavaScript file
+ files: ['*.ts'],
+ rules: {
+ '@typescript-eslint/prefer-ts-expect-error': 'off',
+ // allow using '${val}' with numbers, bool and null types
+ '@typescript-eslint/restrict-template-expressions': [
+ 'error',
+ {
+ allowNumber: true,
+ allowBoolean: true,
+ allowNullish: true,
+ allowNullable: true
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.github/workflows/build.yml b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.github/workflows/build.yml
new file mode 100644
index 000000000..c2ef0af86
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.github/workflows/build.yml
@@ -0,0 +1,89 @@
+name: Build
+on:
+ push:
+ branches:
+ - '*'
+ pull_request:
+ types: [opened, reopened, synchronize]
+
+env:
+ TS_NODE_TRANSPILE_ONLY: 1
+ FORCE_COLORS: 1
+
+# todo: extract shared seto/checkout/install/compile, instead of repeat in each job.
+jobs:
+
+ test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/setup-node@v1
+ with:
+ node-version: '16'
+ - uses: actions/checkout@v1
+ - uses: actions/cache@v2
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+ - run: yarn install
+ - run: yarn compile
+ - run: yarn tsc
+
+ - run: yarn run ci
+
+ gas-checks:
+ runs-on: ubuntu-latest
+ services:
+ localgeth:
+ image: dtr22/geth-dev
+
+ steps:
+ - uses: actions/setup-node@v1
+ with:
+ node-version: '16'
+ - uses: actions/checkout@v1
+ - uses: actions/cache@v2
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+ - run: yarn install
+ - run: yarn compile
+ - run: yarn ci-gas-calc
+
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/setup-node@v1
+ with:
+ node-version: '16'
+ - uses: actions/checkout@v1
+ - uses: actions/cache@v2
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+ - run: yarn install
+ - run: yarn lint
+
+ coverage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/setup-node@v1
+ with:
+ node-version: '16'
+ - uses: actions/checkout@v1
+ - uses: actions/cache@v2
+ with:
+ path: node_modules
+ key: ${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+ - run: yarn install
+
+ - run: yarn compile
+
+ - run: FORCE_COLOR=1 yarn coverage
+ - uses: actions/upload-artifact@v2
+ with:
+ name: solidity-coverage
+ path: |
+ coverage/
+ coverage.json
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solcover.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solcover.js
new file mode 100644
index 000000000..851e37d61
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solcover.js
@@ -0,0 +1,8 @@
+module.exports = {
+ skipFiles: [
+ "test",
+ "samples/bls/lib",
+ "utils/Exec.sol"
+ ],
+ configureYulOptimizer: true,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solhint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solhint.json
new file mode 100644
index 000000000..2b5dda040
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solhint.json
@@ -0,0 +1,12 @@
+{
+ "extends": "solhint:recommended",
+ "rules": {
+ "compiler-version": ["error",">=0.7.5"],
+ "func-visibility": ["off",{"ignoreConstructors":true}],
+ "custom-errors": ["off"],
+ "explicit-types": ["warn", "explicit"],
+ "no-global-import": ["off"],
+ "immutable-vars-naming": ["off"],
+ "mark-callable-contracts": ["off"]
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solhintignore b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solhintignore
new file mode 100644
index 000000000..4972aa1be
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/.solhintignore
@@ -0,0 +1 @@
+contracts/samples/bls/lib/
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/LICENSE b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/README.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/README.md
new file mode 100644
index 000000000..57216f827
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/README.md
@@ -0,0 +1,11 @@
+Implementation of contracts for [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) account abstraction via alternative mempool.
+
+# Resources
+
+[Vitalik's post on account abstraction without Ethereum protocol changes](https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a)
+
+[Discord server](http://discord.gg/fbDyENb6Y9)
+
+[Bundler reference implementation](https://github.com/eth-infinitism/bundler)
+
+[Bundler specification test suite](https://github.com/eth-infinitism/bundler-spec-tests)
diff --git "a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" "b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf"
new file mode 100644
index 000000000..7050f47a6
Binary files /dev/null and "b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/audits/EIP_4337_\342\200\223_Ethereum_Account_Abstraction_Incremental_Audit_Feb_2023.pdf" differ
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/BaseAccount.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/BaseAccount.sol
new file mode 100644
index 000000000..459fc6ab3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/BaseAccount.sol
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable avoid-low-level-calls */
+/* solhint-disable no-empty-blocks */
+
+import "../interfaces/IAccount.sol";
+import "../interfaces/IEntryPoint.sol";
+import "./UserOperationLib.sol";
+
+/**
+ * Basic account implementation.
+ * This contract provides the basic logic for implementing the IAccount interface - validateUserOp
+ * Specific account implementation should inherit it and provide the account-specific logic.
+ */
+abstract contract BaseAccount is IAccount {
+ using UserOperationLib for PackedUserOperation;
+
+ /**
+ * Return the account nonce.
+ * This method returns the next sequential nonce.
+ * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`
+ */
+ function getNonce() public view virtual returns (uint256) {
+ return entryPoint().getNonce(address(this), 0);
+ }
+
+ /**
+ * Return the entryPoint used by this account.
+ * Subclass should return the current entryPoint used by this account.
+ */
+ function entryPoint() public view virtual returns (IEntryPoint);
+
+ /// @inheritdoc IAccount
+ function validateUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingAccountFunds
+ ) external virtual override returns (uint256 validationData) {
+ _requireFromEntryPoint();
+ validationData = _validateSignature(userOp, userOpHash);
+ _validateNonce(userOp.nonce);
+ _payPrefund(missingAccountFunds);
+ }
+
+ /**
+ * Ensure the request comes from the known entrypoint.
+ */
+ function _requireFromEntryPoint() internal view virtual {
+ require(
+ msg.sender == address(entryPoint()),
+ "account: not from EntryPoint"
+ );
+ }
+
+ /**
+ * Validate the signature is valid for this message.
+ * @param userOp - Validate the userOp.signature field.
+ * @param userOpHash - Convenient field: the hash of the request, to check the signature against.
+ * (also hashes the entrypoint and chain id)
+ * @return validationData - Signature and time-range of this operation.
+ * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,
+ * otherwise, an address of an aggregator contract.
+ * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite"
+ * <6-byte> validAfter - first timestamp this operation is valid
+ * If the account doesn't use time-range, it is enough to return
+ * SIG_VALIDATION_FAILED value (1) for signature failure.
+ * Note that the validation code cannot use block.timestamp (or block.number) directly.
+ */
+ function _validateSignature(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash
+ ) internal virtual returns (uint256 validationData);
+
+ /**
+ * Validate the nonce of the UserOperation.
+ * This method may validate the nonce requirement of this account.
+ * e.g.
+ * To limit the nonce to use sequenced UserOps only (no "out of order" UserOps):
+ * `require(nonce < type(uint64).max)`
+ * For a hypothetical account that *requires* the nonce to be out-of-order:
+ * `require(nonce & type(uint64).max == 0)`
+ *
+ * The actual nonce uniqueness is managed by the EntryPoint, and thus no other
+ * action is needed by the account itself.
+ *
+ * @param nonce to validate
+ *
+ * solhint-disable-next-line no-empty-blocks
+ */
+ function _validateNonce(uint256 nonce) internal view virtual {
+ }
+
+ /**
+ * Sends to the entrypoint (msg.sender) the missing funds for this transaction.
+ * SubClass MAY override this method for better funds management
+ * (e.g. send to the entryPoint more than the minimum required, so that in future transactions
+ * it will not be required to send again).
+ * @param missingAccountFunds - The minimum value this method should send the entrypoint.
+ * This value MAY be zero, in case there is enough deposit,
+ * or the userOp has a paymaster.
+ */
+ function _payPrefund(uint256 missingAccountFunds) internal virtual {
+ if (missingAccountFunds != 0) {
+ (bool success, ) = payable(msg.sender).call{
+ value: missingAccountFunds,
+ gas: type(uint256).max
+ }("");
+ (success);
+ //ignore failure (its EntryPoint's job to verify, not account.)
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/BasePaymaster.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/BasePaymaster.sol
new file mode 100644
index 000000000..9bcb6fe63
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/BasePaymaster.sol
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable reason-string */
+
+import "@openzeppelin/contracts/access/Ownable.sol";
+import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
+import "../interfaces/IPaymaster.sol";
+import "../interfaces/IEntryPoint.sol";
+import "./UserOperationLib.sol";
+/**
+ * Helper class for creating a paymaster.
+ * provides helper methods for staking.
+ * Validates that the postOp is called only by the entryPoint.
+ */
+abstract contract BasePaymaster is IPaymaster, Ownable {
+ IEntryPoint public immutable entryPoint;
+
+ uint256 internal constant PAYMASTER_VALIDATION_GAS_OFFSET = UserOperationLib.PAYMASTER_VALIDATION_GAS_OFFSET;
+ uint256 internal constant PAYMASTER_POSTOP_GAS_OFFSET = UserOperationLib.PAYMASTER_POSTOP_GAS_OFFSET;
+ uint256 internal constant PAYMASTER_DATA_OFFSET = UserOperationLib.PAYMASTER_DATA_OFFSET;
+
+ constructor(IEntryPoint _entryPoint) Ownable(msg.sender) {
+ _validateEntryPointInterface(_entryPoint);
+ entryPoint = _entryPoint;
+ }
+
+ //sanity check: make sure this EntryPoint was compiled against the same
+ // IEntryPoint of this paymaster
+ function _validateEntryPointInterface(IEntryPoint _entryPoint) internal virtual {
+ require(IERC165(address(_entryPoint)).supportsInterface(type(IEntryPoint).interfaceId), "IEntryPoint interface mismatch");
+ }
+
+ /// @inheritdoc IPaymaster
+ function validatePaymasterUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 maxCost
+ ) external override returns (bytes memory context, uint256 validationData) {
+ _requireFromEntryPoint();
+ return _validatePaymasterUserOp(userOp, userOpHash, maxCost);
+ }
+
+ /**
+ * Validate a user operation.
+ * @param userOp - The user operation.
+ * @param userOpHash - The hash of the user operation.
+ * @param maxCost - The maximum cost of the user operation.
+ */
+ function _validatePaymasterUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 maxCost
+ ) internal virtual returns (bytes memory context, uint256 validationData);
+
+ /// @inheritdoc IPaymaster
+ function postOp(
+ PostOpMode mode,
+ bytes calldata context,
+ uint256 actualGasCost,
+ uint256 actualUserOpFeePerGas
+ ) external override {
+ _requireFromEntryPoint();
+ _postOp(mode, context, actualGasCost, actualUserOpFeePerGas);
+ }
+
+ /**
+ * Post-operation handler.
+ * (verified to be called only through the entryPoint)
+ * @dev If subclass returns a non-empty context from validatePaymasterUserOp,
+ * it must also implement this method.
+ * @param mode - Enum with the following options:
+ * opSucceeded - User operation succeeded.
+ * opReverted - User op reverted. The paymaster still has to pay for gas.
+ * postOpReverted - never passed in a call to postOp().
+ * @param context - The context value returned by validatePaymasterUserOp
+ * @param actualGasCost - Actual gas used so far (without this postOp call).
+ * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas
+ * and maxPriorityFee (and basefee)
+ * It is not the same as tx.gasprice, which is what the bundler pays.
+ */
+ function _postOp(
+ PostOpMode mode,
+ bytes calldata context,
+ uint256 actualGasCost,
+ uint256 actualUserOpFeePerGas
+ ) internal virtual {
+ (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params
+ // subclass must override this method if validatePaymasterUserOp returns a context
+ revert("must override");
+ }
+
+ /**
+ * Add a deposit for this paymaster, used for paying for transaction fees.
+ */
+ function deposit() public payable {
+ entryPoint.depositTo{value: msg.value}(address(this));
+ }
+
+ /**
+ * Withdraw value from the deposit.
+ * @param withdrawAddress - Target to send to.
+ * @param amount - Amount to withdraw.
+ */
+ function withdrawTo(
+ address payable withdrawAddress,
+ uint256 amount
+ ) public onlyOwner {
+ entryPoint.withdrawTo(withdrawAddress, amount);
+ }
+
+ /**
+ * Add stake for this paymaster.
+ * This method can also carry eth value to add to the current stake.
+ * @param unstakeDelaySec - The unstake delay for this paymaster. Can only be increased.
+ */
+ function addStake(uint32 unstakeDelaySec) external payable onlyOwner {
+ entryPoint.addStake{value: msg.value}(unstakeDelaySec);
+ }
+
+ /**
+ * Return current paymaster's deposit on the entryPoint.
+ */
+ function getDeposit() public view returns (uint256) {
+ return entryPoint.balanceOf(address(this));
+ }
+
+ /**
+ * Unlock the stake, in order to withdraw it.
+ * The paymaster can't serve requests once unlocked, until it calls addStake again
+ */
+ function unlockStake() external onlyOwner {
+ entryPoint.unlockStake();
+ }
+
+ /**
+ * Withdraw the entire paymaster's stake.
+ * stake must be unlocked first (and then wait for the unstakeDelay to be over)
+ * @param withdrawAddress - The address to send withdrawn value.
+ */
+ function withdrawStake(address payable withdrawAddress) external onlyOwner {
+ entryPoint.withdrawStake(withdrawAddress);
+ }
+
+ /**
+ * Validate the call is made from a valid entrypoint
+ */
+ function _requireFromEntryPoint() internal virtual {
+ require(msg.sender == address(entryPoint), "Sender not EntryPoint");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/EntryPoint.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/EntryPoint.sol
new file mode 100644
index 000000000..44501524d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/EntryPoint.sol
@@ -0,0 +1,800 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+/* solhint-disable avoid-low-level-calls */
+/* solhint-disable no-inline-assembly */
+
+import "../interfaces/IAccount.sol";
+import "../interfaces/IAccountExecute.sol";
+import "../interfaces/IPaymaster.sol";
+import "../interfaces/IEntryPoint.sol";
+
+import "../utils/Exec.sol";
+import "./StakeManager.sol";
+import "./SenderCreator.sol";
+import "./Helpers.sol";
+import "./NonceManager.sol";
+import "./UserOperationLib.sol";
+
+import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
+import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
+
+/*
+ * Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
+ * Only one instance required on each chain.
+ */
+
+/// @custom:security-contact https://bounty.ethereum.org
+contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard, ERC165 {
+
+ using UserOperationLib for PackedUserOperation;
+
+ SenderCreator private immutable _senderCreator = new SenderCreator();
+
+ function senderCreator() internal view virtual returns (SenderCreator) {
+ return _senderCreator;
+ }
+
+ //compensate for innerHandleOps' emit message and deposit refund.
+ // allow some slack for future gas price changes.
+ uint256 private constant INNER_GAS_OVERHEAD = 10000;
+
+ // Marker for inner call revert on out of gas
+ bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead";
+ bytes32 private constant INNER_REVERT_LOW_PREFUND = hex"deadaa51";
+
+ uint256 private constant REVERT_REASON_MAX_LEN = 2048;
+ uint256 private constant PENALTY_PERCENT = 10;
+
+ /// @inheritdoc IERC165
+ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
+ // note: solidity "type(IEntryPoint).interfaceId" is without inherited methods but we want to check everything
+ return interfaceId == (type(IEntryPoint).interfaceId ^ type(IStakeManager).interfaceId ^ type(INonceManager).interfaceId) ||
+ interfaceId == type(IEntryPoint).interfaceId ||
+ interfaceId == type(IStakeManager).interfaceId ||
+ interfaceId == type(INonceManager).interfaceId ||
+ super.supportsInterface(interfaceId);
+ }
+
+ /**
+ * Compensate the caller's beneficiary address with the collected fees of all UserOperations.
+ * @param beneficiary - The address to receive the fees.
+ * @param amount - Amount to transfer.
+ */
+ function _compensate(address payable beneficiary, uint256 amount) internal {
+ require(beneficiary != address(0), "AA90 invalid beneficiary");
+ (bool success, ) = beneficiary.call{value: amount}("");
+ require(success, "AA91 failed send to beneficiary");
+ }
+
+ /**
+ * Execute a user operation.
+ * @param opIndex - Index into the opInfo array.
+ * @param userOp - The userOp to execute.
+ * @param opInfo - The opInfo filled by validatePrepayment for this userOp.
+ * @return collected - The total amount this userOp paid.
+ */
+ function _executeUserOp(
+ uint256 opIndex,
+ PackedUserOperation calldata userOp,
+ UserOpInfo memory opInfo
+ )
+ internal
+ returns
+ (uint256 collected) {
+ uint256 preGas = gasleft();
+ bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);
+ bool success;
+ {
+ uint256 saveFreePtr;
+ assembly ("memory-safe") {
+ saveFreePtr := mload(0x40)
+ }
+ bytes calldata callData = userOp.callData;
+ bytes memory innerCall;
+ bytes4 methodSig;
+ assembly {
+ let len := callData.length
+ if gt(len, 3) {
+ methodSig := calldataload(callData.offset)
+ }
+ }
+ if (methodSig == IAccountExecute.executeUserOp.selector) {
+ bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash));
+ innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context));
+ } else
+ {
+ innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context));
+ }
+ assembly ("memory-safe") {
+ success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32)
+ collected := mload(0)
+ mstore(0x40, saveFreePtr)
+ }
+ }
+ if (!success) {
+ bytes32 innerRevertCode;
+ assembly ("memory-safe") {
+ let len := returndatasize()
+ if eq(32,len) {
+ returndatacopy(0, 0, 32)
+ innerRevertCode := mload(0)
+ }
+ }
+ if (innerRevertCode == INNER_OUT_OF_GAS) {
+ // handleOps was called with gas limit too low. abort entire bundle.
+ //can only be caused by bundler (leaving not enough gas for inner call)
+ revert FailedOp(opIndex, "AA95 out of gas");
+ } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) {
+ // innerCall reverted on prefund too low. treat entire prefund as "gas cost"
+ uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
+ uint256 actualGasCost = opInfo.prefund;
+ emitPrefundTooLow(opInfo);
+ emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
+ collected = actualGasCost;
+ } else {
+ emit PostOpRevertReason(
+ opInfo.userOpHash,
+ opInfo.mUserOp.sender,
+ opInfo.mUserOp.nonce,
+ Exec.getReturnData(REVERT_REASON_MAX_LEN)
+ );
+
+ uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
+ collected = _postExecution(
+ IPaymaster.PostOpMode.postOpReverted,
+ opInfo,
+ context,
+ actualGas
+ );
+ }
+ }
+ }
+
+ function emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas) internal virtual {
+ emit UserOperationEvent(
+ opInfo.userOpHash,
+ opInfo.mUserOp.sender,
+ opInfo.mUserOp.paymaster,
+ opInfo.mUserOp.nonce,
+ success,
+ actualGasCost,
+ actualGas
+ );
+ }
+
+ function emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual {
+ emit UserOperationPrefundTooLow(
+ opInfo.userOpHash,
+ opInfo.mUserOp.sender,
+ opInfo.mUserOp.nonce
+ );
+ }
+
+ /// @inheritdoc IEntryPoint
+ function handleOps(
+ PackedUserOperation[] calldata ops,
+ address payable beneficiary
+ ) public nonReentrant {
+ uint256 opslen = ops.length;
+ UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);
+
+ unchecked {
+ for (uint256 i = 0; i < opslen; i++) {
+ UserOpInfo memory opInfo = opInfos[i];
+ (
+ uint256 validationData,
+ uint256 pmValidationData
+ ) = _validatePrepayment(i, ops[i], opInfo);
+ _validateAccountAndPaymasterValidationData(
+ i,
+ validationData,
+ pmValidationData,
+ address(0)
+ );
+ }
+
+ uint256 collected = 0;
+ emit BeforeExecution();
+
+ for (uint256 i = 0; i < opslen; i++) {
+ collected += _executeUserOp(i, ops[i], opInfos[i]);
+ }
+
+ _compensate(beneficiary, collected);
+ }
+ }
+
+ /// @inheritdoc IEntryPoint
+ function handleAggregatedOps(
+ UserOpsPerAggregator[] calldata opsPerAggregator,
+ address payable beneficiary
+ ) public nonReentrant {
+
+ uint256 opasLen = opsPerAggregator.length;
+ uint256 totalOps = 0;
+ for (uint256 i = 0; i < opasLen; i++) {
+ UserOpsPerAggregator calldata opa = opsPerAggregator[i];
+ PackedUserOperation[] calldata ops = opa.userOps;
+ IAggregator aggregator = opa.aggregator;
+
+ //address(1) is special marker of "signature error"
+ require(
+ address(aggregator) != address(1),
+ "AA96 invalid aggregator"
+ );
+
+ if (address(aggregator) != address(0)) {
+ // solhint-disable-next-line no-empty-blocks
+ try aggregator.validateSignatures(ops, opa.signature) {} catch {
+ revert SignatureValidationFailed(address(aggregator));
+ }
+ }
+
+ totalOps += ops.length;
+ }
+
+ UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);
+
+ uint256 opIndex = 0;
+ for (uint256 a = 0; a < opasLen; a++) {
+ UserOpsPerAggregator calldata opa = opsPerAggregator[a];
+ PackedUserOperation[] calldata ops = opa.userOps;
+ IAggregator aggregator = opa.aggregator;
+
+ uint256 opslen = ops.length;
+ for (uint256 i = 0; i < opslen; i++) {
+ UserOpInfo memory opInfo = opInfos[opIndex];
+ (
+ uint256 validationData,
+ uint256 paymasterValidationData
+ ) = _validatePrepayment(opIndex, ops[i], opInfo);
+ _validateAccountAndPaymasterValidationData(
+ i,
+ validationData,
+ paymasterValidationData,
+ address(aggregator)
+ );
+ opIndex++;
+ }
+ }
+
+ emit BeforeExecution();
+
+ uint256 collected = 0;
+ opIndex = 0;
+ for (uint256 a = 0; a < opasLen; a++) {
+ UserOpsPerAggregator calldata opa = opsPerAggregator[a];
+ emit SignatureAggregatorChanged(address(opa.aggregator));
+ PackedUserOperation[] calldata ops = opa.userOps;
+ uint256 opslen = ops.length;
+
+ for (uint256 i = 0; i < opslen; i++) {
+ collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);
+ opIndex++;
+ }
+ }
+ emit SignatureAggregatorChanged(address(0));
+
+ _compensate(beneficiary, collected);
+ }
+
+ /**
+ * A memory copy of UserOp static fields only.
+ * Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.
+ */
+ struct MemoryUserOp {
+ address sender;
+ uint256 nonce;
+ uint256 verificationGasLimit;
+ uint256 callGasLimit;
+ uint256 paymasterVerificationGasLimit;
+ uint256 paymasterPostOpGasLimit;
+ uint256 preVerificationGas;
+ address paymaster;
+ uint256 maxFeePerGas;
+ uint256 maxPriorityFeePerGas;
+ }
+
+ struct UserOpInfo {
+ MemoryUserOp mUserOp;
+ bytes32 userOpHash;
+ uint256 prefund;
+ uint256 contextOffset;
+ uint256 preOpGas;
+ }
+
+ /**
+ * Inner function to handle a UserOperation.
+ * Must be declared "external" to open a call context, but it can only be called by handleOps.
+ * @param callData - The callData to execute.
+ * @param opInfo - The UserOpInfo struct.
+ * @param context - The context bytes.
+ * @return actualGasCost - the actual cost in eth this UserOperation paid for gas
+ */
+ function innerHandleOp(
+ bytes memory callData,
+ UserOpInfo memory opInfo,
+ bytes calldata context
+ ) external returns (uint256 actualGasCost) {
+ uint256 preGas = gasleft();
+ require(msg.sender == address(this), "AA92 internal call only");
+ MemoryUserOp memory mUserOp = opInfo.mUserOp;
+
+ uint256 callGasLimit = mUserOp.callGasLimit;
+ unchecked {
+ // handleOps was called with gas limit too low. abort entire bundle.
+ if (
+ gasleft() * 63 / 64 <
+ callGasLimit +
+ mUserOp.paymasterPostOpGasLimit +
+ INNER_GAS_OVERHEAD
+ ) {
+ assembly ("memory-safe") {
+ mstore(0, INNER_OUT_OF_GAS)
+ revert(0, 32)
+ }
+ }
+ }
+
+ IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;
+ if (callData.length > 0) {
+ bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);
+ if (!success) {
+ bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);
+ if (result.length > 0) {
+ emit UserOperationRevertReason(
+ opInfo.userOpHash,
+ mUserOp.sender,
+ mUserOp.nonce,
+ result
+ );
+ }
+ mode = IPaymaster.PostOpMode.opReverted;
+ }
+ }
+
+ unchecked {
+ uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
+ return _postExecution(mode, opInfo, context, actualGas);
+ }
+ }
+
+ /// @inheritdoc IEntryPoint
+ function getUserOpHash(
+ PackedUserOperation calldata userOp
+ ) public view returns (bytes32) {
+ return
+ keccak256(abi.encode(userOp.hash(), address(this), block.chainid));
+ }
+
+ /**
+ * Copy general fields from userOp into the memory opInfo structure.
+ * @param userOp - The user operation.
+ * @param mUserOp - The memory user operation.
+ */
+ function _copyUserOpToMemory(
+ PackedUserOperation calldata userOp,
+ MemoryUserOp memory mUserOp
+ ) internal pure {
+ mUserOp.sender = userOp.sender;
+ mUserOp.nonce = userOp.nonce;
+ (mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits);
+ mUserOp.preVerificationGas = userOp.preVerificationGas;
+ (mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees);
+ bytes calldata paymasterAndData = userOp.paymasterAndData;
+ if (paymasterAndData.length > 0) {
+ require(
+ paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET,
+ "AA93 invalid paymasterAndData"
+ );
+ (mUserOp.paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);
+ } else {
+ mUserOp.paymaster = address(0);
+ mUserOp.paymasterVerificationGasLimit = 0;
+ mUserOp.paymasterPostOpGasLimit = 0;
+ }
+ }
+
+ /**
+ * Get the required prefunded gas fee amount for an operation.
+ * @param mUserOp - The user operation in memory.
+ */
+ function _getRequiredPrefund(
+ MemoryUserOp memory mUserOp
+ ) internal pure returns (uint256 requiredPrefund) {
+ unchecked {
+ uint256 requiredGas = mUserOp.verificationGasLimit +
+ mUserOp.callGasLimit +
+ mUserOp.paymasterVerificationGasLimit +
+ mUserOp.paymasterPostOpGasLimit +
+ mUserOp.preVerificationGas;
+
+ requiredPrefund = requiredGas * mUserOp.maxFeePerGas;
+ }
+ }
+
+ /**
+ * Create sender smart contract account if init code is provided.
+ * @param opIndex - The operation index.
+ * @param opInfo - The operation info.
+ * @param initCode - The init code for the smart contract account.
+ */
+ function _createSenderIfNeeded(
+ uint256 opIndex,
+ UserOpInfo memory opInfo,
+ bytes calldata initCode
+ ) internal {
+ if (initCode.length != 0) {
+ address sender = opInfo.mUserOp.sender;
+ if (sender.code.length != 0)
+ revert FailedOp(opIndex, "AA10 sender already constructed");
+ address sender1 = senderCreator().createSender{
+ gas: opInfo.mUserOp.verificationGasLimit
+ }(initCode);
+ if (sender1 == address(0))
+ revert FailedOp(opIndex, "AA13 initCode failed or OOG");
+ if (sender1 != sender)
+ revert FailedOp(opIndex, "AA14 initCode must return sender");
+ if (sender1.code.length == 0)
+ revert FailedOp(opIndex, "AA15 initCode must create sender");
+ address factory = address(bytes20(initCode[0:20]));
+ emit AccountDeployed(
+ opInfo.userOpHash,
+ sender,
+ factory,
+ opInfo.mUserOp.paymaster
+ );
+ }
+ }
+
+ /// @inheritdoc IEntryPoint
+ function getSenderAddress(bytes calldata initCode) public {
+ address sender = senderCreator().createSender(initCode);
+ revert SenderAddressResult(sender);
+ }
+
+ /**
+ * Call account.validateUserOp.
+ * Revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.
+ * Decrement account's deposit if needed.
+ * @param opIndex - The operation index.
+ * @param op - The user operation.
+ * @param opInfo - The operation info.
+ * @param requiredPrefund - The required prefund amount.
+ */
+ function _validateAccountPrepayment(
+ uint256 opIndex,
+ PackedUserOperation calldata op,
+ UserOpInfo memory opInfo,
+ uint256 requiredPrefund,
+ uint256 verificationGasLimit
+ )
+ internal
+ returns (
+ uint256 validationData
+ )
+ {
+ unchecked {
+ MemoryUserOp memory mUserOp = opInfo.mUserOp;
+ address sender = mUserOp.sender;
+ _createSenderIfNeeded(opIndex, opInfo, op.initCode);
+ address paymaster = mUserOp.paymaster;
+ uint256 missingAccountFunds = 0;
+ if (paymaster == address(0)) {
+ uint256 bal = balanceOf(sender);
+ missingAccountFunds = bal > requiredPrefund
+ ? 0
+ : requiredPrefund - bal;
+ }
+ try
+ IAccount(sender).validateUserOp{
+ gas: verificationGasLimit
+ }(op, opInfo.userOpHash, missingAccountFunds)
+ returns (uint256 _validationData) {
+ validationData = _validationData;
+ } catch {
+ revert FailedOpWithRevert(opIndex, "AA23 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
+ }
+ if (paymaster == address(0)) {
+ DepositInfo storage senderInfo = deposits[sender];
+ uint256 deposit = senderInfo.deposit;
+ if (requiredPrefund > deposit) {
+ revert FailedOp(opIndex, "AA21 didn't pay prefund");
+ }
+ senderInfo.deposit = deposit - requiredPrefund;
+ }
+ }
+ }
+
+ /**
+ * In case the request has a paymaster:
+ * - Validate paymaster has enough deposit.
+ * - Call paymaster.validatePaymasterUserOp.
+ * - Revert with proper FailedOp in case paymaster reverts.
+ * - Decrement paymaster's deposit.
+ * @param opIndex - The operation index.
+ * @param op - The user operation.
+ * @param opInfo - The operation info.
+ * @param requiredPreFund - The required prefund amount.
+ */
+ function _validatePaymasterPrepayment(
+ uint256 opIndex,
+ PackedUserOperation calldata op,
+ UserOpInfo memory opInfo,
+ uint256 requiredPreFund
+ ) internal returns (bytes memory context, uint256 validationData) {
+ unchecked {
+ uint256 preGas = gasleft();
+ MemoryUserOp memory mUserOp = opInfo.mUserOp;
+ address paymaster = mUserOp.paymaster;
+ DepositInfo storage paymasterInfo = deposits[paymaster];
+ uint256 deposit = paymasterInfo.deposit;
+ if (deposit < requiredPreFund) {
+ revert FailedOp(opIndex, "AA31 paymaster deposit too low");
+ }
+ paymasterInfo.deposit = deposit - requiredPreFund;
+ uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;
+ try
+ IPaymaster(paymaster).validatePaymasterUserOp{gas: pmVerificationGasLimit}(
+ op,
+ opInfo.userOpHash,
+ requiredPreFund
+ )
+ returns (bytes memory _context, uint256 _validationData) {
+ context = _context;
+ validationData = _validationData;
+ } catch {
+ revert FailedOpWithRevert(opIndex, "AA33 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
+ }
+ if (preGas - gasleft() > pmVerificationGasLimit) {
+ revert FailedOp(opIndex, "AA36 over paymasterVerificationGasLimit");
+ }
+ }
+ }
+
+ /**
+ * Revert if either account validationData or paymaster validationData is expired.
+ * @param opIndex - The operation index.
+ * @param validationData - The account validationData.
+ * @param paymasterValidationData - The paymaster validationData.
+ * @param expectedAggregator - The expected aggregator.
+ */
+ function _validateAccountAndPaymasterValidationData(
+ uint256 opIndex,
+ uint256 validationData,
+ uint256 paymasterValidationData,
+ address expectedAggregator
+ ) internal view {
+ (address aggregator, bool outOfTimeRange) = _getValidationData(
+ validationData
+ );
+ if (expectedAggregator != aggregator) {
+ revert FailedOp(opIndex, "AA24 signature error");
+ }
+ if (outOfTimeRange) {
+ revert FailedOp(opIndex, "AA22 expired or not due");
+ }
+ // pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.
+ // Non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation).
+ address pmAggregator;
+ (pmAggregator, outOfTimeRange) = _getValidationData(
+ paymasterValidationData
+ );
+ if (pmAggregator != address(0)) {
+ revert FailedOp(opIndex, "AA34 signature error");
+ }
+ if (outOfTimeRange) {
+ revert FailedOp(opIndex, "AA32 paymaster expired or not due");
+ }
+ }
+
+ /**
+ * Parse validationData into its components.
+ * @param validationData - The packed validation data (sigFailed, validAfter, validUntil).
+ * @return aggregator the aggregator of the validationData
+ * @return outOfTimeRange true if current time is outside the time range of this validationData.
+ */
+ function _getValidationData(
+ uint256 validationData
+ ) internal view returns (address aggregator, bool outOfTimeRange) {
+ if (validationData == 0) {
+ return (address(0), false);
+ }
+ ValidationData memory data = _parseValidationData(validationData);
+ // solhint-disable-next-line not-rely-on-time
+ outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;
+ aggregator = data.aggregator;
+ }
+
+ /**
+ * Validate account and paymaster (if defined) and
+ * also make sure total validation doesn't exceed verificationGasLimit.
+ * This method is called off-chain (simulateValidation()) and on-chain (from handleOps)
+ * @param opIndex - The index of this userOp into the "opInfos" array.
+ * @param userOp - The userOp to validate.
+ */
+ function _validatePrepayment(
+ uint256 opIndex,
+ PackedUserOperation calldata userOp,
+ UserOpInfo memory outOpInfo
+ )
+ internal
+ returns (uint256 validationData, uint256 paymasterValidationData)
+ {
+ uint256 preGas = gasleft();
+ MemoryUserOp memory mUserOp = outOpInfo.mUserOp;
+ _copyUserOpToMemory(userOp, mUserOp);
+ outOpInfo.userOpHash = getUserOpHash(userOp);
+
+ // Validate all numeric values in userOp are well below 128 bit, so they can safely be added
+ // and multiplied without causing overflow.
+ uint256 verificationGasLimit = mUserOp.verificationGasLimit;
+ uint256 maxGasValues = mUserOp.preVerificationGas |
+ verificationGasLimit |
+ mUserOp.callGasLimit |
+ mUserOp.paymasterVerificationGasLimit |
+ mUserOp.paymasterPostOpGasLimit |
+ mUserOp.maxFeePerGas |
+ mUserOp.maxPriorityFeePerGas;
+ require(maxGasValues <= type(uint120).max, "AA94 gas values overflow");
+
+ uint256 requiredPreFund = _getRequiredPrefund(mUserOp);
+ validationData = _validateAccountPrepayment(
+ opIndex,
+ userOp,
+ outOpInfo,
+ requiredPreFund,
+ verificationGasLimit
+ );
+
+ if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {
+ revert FailedOp(opIndex, "AA25 invalid account nonce");
+ }
+
+ unchecked {
+ if (preGas - gasleft() > verificationGasLimit) {
+ revert FailedOp(opIndex, "AA26 over verificationGasLimit");
+ }
+ }
+
+ bytes memory context;
+ if (mUserOp.paymaster != address(0)) {
+ (context, paymasterValidationData) = _validatePaymasterPrepayment(
+ opIndex,
+ userOp,
+ outOpInfo,
+ requiredPreFund
+ );
+ }
+ unchecked {
+ outOpInfo.prefund = requiredPreFund;
+ outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);
+ outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;
+ }
+ }
+
+ /**
+ * Process post-operation, called just after the callData is executed.
+ * If a paymaster is defined and its validation returned a non-empty context, its postOp is called.
+ * The excess amount is refunded to the account (or paymaster - if it was used in the request).
+ * @param mode - Whether is called from innerHandleOp, or outside (postOpReverted).
+ * @param opInfo - UserOp fields and info collected during validation.
+ * @param context - The context returned in validatePaymasterUserOp.
+ * @param actualGas - The gas used so far by this user operation.
+ */
+ function _postExecution(
+ IPaymaster.PostOpMode mode,
+ UserOpInfo memory opInfo,
+ bytes memory context,
+ uint256 actualGas
+ ) private returns (uint256 actualGasCost) {
+ uint256 preGas = gasleft();
+ unchecked {
+ address refundAddress;
+ MemoryUserOp memory mUserOp = opInfo.mUserOp;
+ uint256 gasPrice = getUserOpGasPrice(mUserOp);
+
+ address paymaster = mUserOp.paymaster;
+ if (paymaster == address(0)) {
+ refundAddress = mUserOp.sender;
+ } else {
+ refundAddress = paymaster;
+ if (context.length > 0) {
+ actualGasCost = actualGas * gasPrice;
+ if (mode != IPaymaster.PostOpMode.postOpReverted) {
+ try IPaymaster(paymaster).postOp{
+ gas: mUserOp.paymasterPostOpGasLimit
+ }(mode, context, actualGasCost, gasPrice)
+ // solhint-disable-next-line no-empty-blocks
+ {} catch {
+ bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN);
+ revert PostOpReverted(reason);
+ }
+ }
+ }
+ }
+ actualGas += preGas - gasleft();
+
+ // Calculating a penalty for unused execution gas
+ {
+ uint256 executionGasLimit = mUserOp.callGasLimit + mUserOp.paymasterPostOpGasLimit;
+ uint256 executionGasUsed = actualGas - opInfo.preOpGas;
+ // this check is required for the gas used within EntryPoint and not covered by explicit gas limits
+ if (executionGasLimit > executionGasUsed) {
+ uint256 unusedGas = executionGasLimit - executionGasUsed;
+ uint256 unusedGasPenalty = (unusedGas * PENALTY_PERCENT) / 100;
+ actualGas += unusedGasPenalty;
+ }
+ }
+
+ actualGasCost = actualGas * gasPrice;
+ uint256 prefund = opInfo.prefund;
+ if (prefund < actualGasCost) {
+ if (mode == IPaymaster.PostOpMode.postOpReverted) {
+ actualGasCost = prefund;
+ emitPrefundTooLow(opInfo);
+ emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
+ } else {
+ assembly ("memory-safe") {
+ mstore(0, INNER_REVERT_LOW_PREFUND)
+ revert(0, 32)
+ }
+ }
+ } else {
+ uint256 refund = prefund - actualGasCost;
+ _incrementDeposit(refundAddress, refund);
+ bool success = mode == IPaymaster.PostOpMode.opSucceeded;
+ emitUserOperationEvent(opInfo, success, actualGasCost, actualGas);
+ }
+ } // unchecked
+ }
+
+ /**
+ * The gas price this UserOp agrees to pay.
+ * Relayer/block builder might submit the TX with higher priorityFee, but the user should not.
+ * @param mUserOp - The userOp to get the gas price from.
+ */
+ function getUserOpGasPrice(
+ MemoryUserOp memory mUserOp
+ ) internal view returns (uint256) {
+ unchecked {
+ uint256 maxFeePerGas = mUserOp.maxFeePerGas;
+ uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
+ if (maxFeePerGas == maxPriorityFeePerGas) {
+ //legacy mode (for networks that don't support basefee opcode)
+ return maxFeePerGas;
+ }
+ return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
+ }
+ }
+
+ /**
+ * The offset of the given bytes in memory.
+ * @param data - The bytes to get the offset of.
+ */
+ function getOffsetOfMemoryBytes(
+ bytes memory data
+ ) internal pure returns (uint256 offset) {
+ assembly {
+ offset := data
+ }
+ }
+
+ /**
+ * The bytes in memory at the given offset.
+ * @param offset - The offset to get the bytes from.
+ */
+ function getMemoryBytesFromOffset(
+ uint256 offset
+ ) internal pure returns (bytes memory data) {
+ assembly ("memory-safe") {
+ data := offset
+ }
+ }
+
+ /// @inheritdoc IEntryPoint
+ function delegateAndRevert(address target, bytes calldata data) external {
+ (bool success, bytes memory ret) = target.delegatecall(data);
+ revert DelegateAndRevert(success, ret);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/EntryPointSimulations.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/EntryPointSimulations.sol
new file mode 100644
index 000000000..b8c41ea12
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/EntryPointSimulations.sol
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable avoid-low-level-calls */
+/* solhint-disable no-inline-assembly */
+
+import "./EntryPoint.sol";
+import "../interfaces/IEntryPointSimulations.sol";
+
+/*
+ * This contract inherits the EntryPoint and extends it with the view-only methods that are executed by
+ * the bundler in order to check UserOperation validity and estimate its gas consumption.
+ * This contract should never be deployed on-chain and is only used as a parameter for the "eth_call" request.
+ */
+contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {
+ // solhint-disable-next-line var-name-mixedcase
+ AggregatorStakeInfo private NOT_AGGREGATED = AggregatorStakeInfo(address(0), StakeInfo(0, 0));
+
+ SenderCreator private _senderCreator;
+
+ function initSenderCreator() internal virtual {
+ //this is the address of the first contract created with CREATE by this address.
+ address createdObj = address(uint160(uint256(keccak256(abi.encodePacked(hex"d694", address(this), hex"01")))));
+ _senderCreator = SenderCreator(createdObj);
+ }
+
+ function senderCreator() internal view virtual override returns (SenderCreator) {
+ // return the same senderCreator as real EntryPoint.
+ // this call is slightly (100) more expensive than EntryPoint's access to immutable member
+ return _senderCreator;
+ }
+
+ /**
+ * simulation contract should not be deployed, and specifically, accounts should not trust
+ * it as entrypoint, since the simulation functions don't check the signatures
+ */
+ constructor() {
+ require(block.number < 100, "should not be deployed");
+ }
+
+ /// @inheritdoc IEntryPointSimulations
+ function simulateValidation(
+ PackedUserOperation calldata userOp
+ )
+ external
+ returns (
+ ValidationResult memory
+ ){
+ UserOpInfo memory outOpInfo;
+
+ _simulationOnlyValidations(userOp);
+ (
+ uint256 validationData,
+ uint256 paymasterValidationData
+ ) = _validatePrepayment(0, userOp, outOpInfo);
+ StakeInfo memory paymasterInfo = _getStakeInfo(
+ outOpInfo.mUserOp.paymaster
+ );
+ StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);
+ StakeInfo memory factoryInfo;
+ {
+ bytes calldata initCode = userOp.initCode;
+ address factory = initCode.length >= 20
+ ? address(bytes20(initCode[0 : 20]))
+ : address(0);
+ factoryInfo = _getStakeInfo(factory);
+ }
+
+ address aggregator = address(uint160(validationData));
+ ReturnInfo memory returnInfo = ReturnInfo(
+ outOpInfo.preOpGas,
+ outOpInfo.prefund,
+ validationData,
+ paymasterValidationData,
+ getMemoryBytesFromOffset(outOpInfo.contextOffset)
+ );
+
+ AggregatorStakeInfo memory aggregatorInfo = NOT_AGGREGATED;
+ if (uint160(aggregator) != SIG_VALIDATION_SUCCESS && uint160(aggregator) != SIG_VALIDATION_FAILED) {
+ aggregatorInfo = AggregatorStakeInfo(
+ aggregator,
+ _getStakeInfo(aggregator)
+ );
+ }
+ return ValidationResult(
+ returnInfo,
+ senderInfo,
+ factoryInfo,
+ paymasterInfo,
+ aggregatorInfo
+ );
+ }
+
+ /// @inheritdoc IEntryPointSimulations
+ function simulateHandleOp(
+ PackedUserOperation calldata op,
+ address target,
+ bytes calldata targetCallData
+ )
+ external nonReentrant
+ returns (
+ ExecutionResult memory
+ ){
+ UserOpInfo memory opInfo;
+ _simulationOnlyValidations(op);
+ (
+ uint256 validationData,
+ uint256 paymasterValidationData
+ ) = _validatePrepayment(0, op, opInfo);
+
+ uint256 paid = _executeUserOp(0, op, opInfo);
+ bool targetSuccess;
+ bytes memory targetResult;
+ if (target != address(0)) {
+ (targetSuccess, targetResult) = target.call(targetCallData);
+ }
+ return ExecutionResult(
+ opInfo.preOpGas,
+ paid,
+ validationData,
+ paymasterValidationData,
+ targetSuccess,
+ targetResult
+ );
+ }
+
+ function _simulationOnlyValidations(
+ PackedUserOperation calldata userOp
+ )
+ internal
+ {
+ //initialize senderCreator(). we can't rely on constructor
+ initSenderCreator();
+
+ try
+ this._validateSenderAndPaymaster(
+ userOp.initCode,
+ userOp.sender,
+ userOp.paymasterAndData
+ )
+ // solhint-disable-next-line no-empty-blocks
+ {} catch Error(string memory revertReason) {
+ if (bytes(revertReason).length != 0) {
+ revert FailedOp(0, revertReason);
+ }
+ }
+ }
+
+ /**
+ * Called only during simulation.
+ * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.
+ * @param initCode - The smart account constructor code.
+ * @param sender - The sender address.
+ * @param paymasterAndData - The paymaster address (followed by other params, ignored by this method)
+ */
+ function _validateSenderAndPaymaster(
+ bytes calldata initCode,
+ address sender,
+ bytes calldata paymasterAndData
+ ) external view {
+ if (initCode.length == 0 && sender.code.length == 0) {
+ // it would revert anyway. but give a meaningful message
+ revert("AA20 account not deployed");
+ }
+ if (paymasterAndData.length >= 20) {
+ address paymaster = address(bytes20(paymasterAndData[0 : 20]));
+ if (paymaster.code.length == 0) {
+ // It would revert anyway. but give a meaningful message.
+ revert("AA30 paymaster not deployed");
+ }
+ }
+ // always revert
+ revert("");
+ }
+
+ //make sure depositTo cost is more than normal EntryPoint's cost,
+ // to mitigate DoS vector on the bundler
+ // empiric test showed that without this wrapper, simulation depositTo costs less..
+ function depositTo(address account) public override(IStakeManager, StakeManager) payable {
+ unchecked{
+ // silly code, to waste some gas to make sure depositTo is always little more
+ // expensive than on-chain call
+ uint256 x = 1;
+ while (x < 5) {
+ x++;
+ }
+ StakeManager.depositTo(account);
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/Helpers.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/Helpers.sol
new file mode 100644
index 000000000..857900861
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/Helpers.sol
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable no-inline-assembly */
+
+
+ /*
+ * For simulation purposes, validateUserOp (and validatePaymasterUserOp)
+ * must return this value in case of signature failure, instead of revert.
+ */
+uint256 constant SIG_VALIDATION_FAILED = 1;
+
+
+/*
+ * For simulation purposes, validateUserOp (and validatePaymasterUserOp)
+ * return this value on success.
+ */
+uint256 constant SIG_VALIDATION_SUCCESS = 0;
+
+
+/**
+ * Returned data from validateUserOp.
+ * validateUserOp returns a uint256, which is created by `_packedValidationData` and
+ * parsed by `_parseValidationData`.
+ * @param aggregator - address(0) - The account validated the signature by itself.
+ * address(1) - The account failed to validate the signature.
+ * otherwise - This is an address of a signature aggregator that must
+ * be used to validate the signature.
+ * @param validAfter - This UserOp is valid only after this timestamp.
+ * @param validaUntil - This UserOp is valid only up to this timestamp.
+ */
+struct ValidationData {
+ address aggregator;
+ uint48 validAfter;
+ uint48 validUntil;
+}
+
+/**
+ * Extract sigFailed, validAfter, validUntil.
+ * Also convert zero validUntil to type(uint48).max.
+ * @param validationData - The packed validation data.
+ */
+function _parseValidationData(
+ uint256 validationData
+) pure returns (ValidationData memory data) {
+ address aggregator = address(uint160(validationData));
+ uint48 validUntil = uint48(validationData >> 160);
+ if (validUntil == 0) {
+ validUntil = type(uint48).max;
+ }
+ uint48 validAfter = uint48(validationData >> (48 + 160));
+ return ValidationData(aggregator, validAfter, validUntil);
+}
+
+/**
+ * Helper to pack the return value for validateUserOp.
+ * @param data - The ValidationData to pack.
+ */
+function _packValidationData(
+ ValidationData memory data
+) pure returns (uint256) {
+ return
+ uint160(data.aggregator) |
+ (uint256(data.validUntil) << 160) |
+ (uint256(data.validAfter) << (160 + 48));
+}
+
+/**
+ * Helper to pack the return value for validateUserOp, when not using an aggregator.
+ * @param sigFailed - True for signature failure, false for success.
+ * @param validUntil - Last timestamp this UserOperation is valid (or zero for infinite).
+ * @param validAfter - First timestamp this UserOperation is valid.
+ */
+function _packValidationData(
+ bool sigFailed,
+ uint48 validUntil,
+ uint48 validAfter
+) pure returns (uint256) {
+ return
+ (sigFailed ? 1 : 0) |
+ (uint256(validUntil) << 160) |
+ (uint256(validAfter) << (160 + 48));
+}
+
+/**
+ * keccak function over calldata.
+ * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.
+ */
+ function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
+ assembly ("memory-safe") {
+ let mem := mload(0x40)
+ let len := data.length
+ calldatacopy(mem, data.offset, len)
+ ret := keccak256(mem, len)
+ }
+ }
+
+
+/**
+ * The minimum of two numbers.
+ * @param a - First number.
+ * @param b - Second number.
+ */
+ function min(uint256 a, uint256 b) pure returns (uint256) {
+ return a < b ? a : b;
+ }
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/NonceManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/NonceManager.sol
new file mode 100644
index 000000000..7bef62e99
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/NonceManager.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+import "../interfaces/INonceManager.sol";
+
+/**
+ * nonce management functionality
+ */
+abstract contract NonceManager is INonceManager {
+
+ /**
+ * The next valid sequence number for a given nonce key.
+ */
+ mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;
+
+ /// @inheritdoc INonceManager
+ function getNonce(address sender, uint192 key)
+ public view override returns (uint256 nonce) {
+ return nonceSequenceNumber[sender][key] | (uint256(key) << 64);
+ }
+
+ // allow an account to manually increment its own nonce.
+ // (mainly so that during construction nonce can be made non-zero,
+ // to "absorb" the gas cost of first nonce increment to 1st transaction (construction),
+ // not to 2nd transaction)
+ function incrementNonce(uint192 key) public override {
+ nonceSequenceNumber[msg.sender][key]++;
+ }
+
+ /**
+ * validate nonce uniqueness for this account.
+ * called just after validateUserOp()
+ * @return true if the nonce was incremented successfully.
+ * false if the current nonce doesn't match the given one.
+ */
+ function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {
+
+ uint192 key = uint192(nonce >> 64);
+ uint64 seq = uint64(nonce);
+ return nonceSequenceNumber[sender][key]++ == seq;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/SenderCreator.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/SenderCreator.sol
new file mode 100644
index 000000000..43ea80367
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/SenderCreator.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/**
+ * Helper contract for EntryPoint, to call userOp.initCode from a "neutral" address,
+ * which is explicitly not the entryPoint itself.
+ */
+contract SenderCreator {
+ /**
+ * Call the "initCode" factory to create and return the sender account address.
+ * @param initCode - The initCode value from a UserOp. contains 20 bytes of factory address,
+ * followed by calldata.
+ * @return sender - The returned address of the created account, or zero address on failure.
+ */
+ function createSender(
+ bytes calldata initCode
+ ) external returns (address sender) {
+ address factory = address(bytes20(initCode[0:20]));
+ bytes memory initCallData = initCode[20:];
+ bool success;
+ /* solhint-disable no-inline-assembly */
+ assembly ("memory-safe") {
+ success := call(
+ gas(),
+ factory,
+ 0,
+ add(initCallData, 0x20),
+ mload(initCallData),
+ 0,
+ 32
+ )
+ sender := mload(0)
+ }
+ if (!success) {
+ sender = address(0);
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/StakeManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/StakeManager.sol
new file mode 100644
index 000000000..f90210b7e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/StakeManager.sol
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-3.0-only
+pragma solidity ^0.8.23;
+
+import "../interfaces/IStakeManager.sol";
+
+/* solhint-disable avoid-low-level-calls */
+/* solhint-disable not-rely-on-time */
+
+/**
+ * Manage deposits and stakes.
+ * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).
+ * Stake is value locked for at least "unstakeDelay" by a paymaster.
+ */
+abstract contract StakeManager is IStakeManager {
+ /// maps paymaster to their deposits and stakes
+ mapping(address => DepositInfo) public deposits;
+
+ /// @inheritdoc IStakeManager
+ function getDepositInfo(
+ address account
+ ) public view returns (DepositInfo memory info) {
+ return deposits[account];
+ }
+
+ /**
+ * Internal method to return just the stake info.
+ * @param addr - The account to query.
+ */
+ function _getStakeInfo(
+ address addr
+ ) internal view returns (StakeInfo memory info) {
+ DepositInfo storage depositInfo = deposits[addr];
+ info.stake = depositInfo.stake;
+ info.unstakeDelaySec = depositInfo.unstakeDelaySec;
+ }
+
+ /// @inheritdoc IStakeManager
+ function balanceOf(address account) public view returns (uint256) {
+ return deposits[account].deposit;
+ }
+
+ receive() external payable {
+ depositTo(msg.sender);
+ }
+
+ /**
+ * Increments an account's deposit.
+ * @param account - The account to increment.
+ * @param amount - The amount to increment by.
+ * @return the updated deposit of this account
+ */
+ function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {
+ DepositInfo storage info = deposits[account];
+ uint256 newAmount = info.deposit + amount;
+ info.deposit = newAmount;
+ return newAmount;
+ }
+
+ /**
+ * Add to the deposit of the given account.
+ * @param account - The account to add to.
+ */
+ function depositTo(address account) public virtual payable {
+ uint256 newDeposit = _incrementDeposit(account, msg.value);
+ emit Deposited(account, newDeposit);
+ }
+
+ /**
+ * Add to the account's stake - amount and delay
+ * any pending unstake is first cancelled.
+ * @param unstakeDelaySec The new lock duration before the deposit can be withdrawn.
+ */
+ function addStake(uint32 unstakeDelaySec) public payable {
+ DepositInfo storage info = deposits[msg.sender];
+ require(unstakeDelaySec > 0, "must specify unstake delay");
+ require(
+ unstakeDelaySec >= info.unstakeDelaySec,
+ "cannot decrease unstake time"
+ );
+ uint256 stake = info.stake + msg.value;
+ require(stake > 0, "no stake specified");
+ require(stake <= type(uint112).max, "stake overflow");
+ deposits[msg.sender] = DepositInfo(
+ info.deposit,
+ true,
+ uint112(stake),
+ unstakeDelaySec,
+ 0
+ );
+ emit StakeLocked(msg.sender, stake, unstakeDelaySec);
+ }
+
+ /**
+ * Attempt to unlock the stake.
+ * The value can be withdrawn (using withdrawStake) after the unstake delay.
+ */
+ function unlockStake() external {
+ DepositInfo storage info = deposits[msg.sender];
+ require(info.unstakeDelaySec != 0, "not staked");
+ require(info.staked, "already unstaking");
+ uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;
+ info.withdrawTime = withdrawTime;
+ info.staked = false;
+ emit StakeUnlocked(msg.sender, withdrawTime);
+ }
+
+ /**
+ * Withdraw from the (unlocked) stake.
+ * Must first call unlockStake and wait for the unstakeDelay to pass.
+ * @param withdrawAddress - The address to send withdrawn value.
+ */
+ function withdrawStake(address payable withdrawAddress) external {
+ DepositInfo storage info = deposits[msg.sender];
+ uint256 stake = info.stake;
+ require(stake > 0, "No stake to withdraw");
+ require(info.withdrawTime > 0, "must call unlockStake() first");
+ require(
+ info.withdrawTime <= block.timestamp,
+ "Stake withdrawal is not due"
+ );
+ info.unstakeDelaySec = 0;
+ info.withdrawTime = 0;
+ info.stake = 0;
+ emit StakeWithdrawn(msg.sender, withdrawAddress, stake);
+ (bool success,) = withdrawAddress.call{value: stake}("");
+ require(success, "failed to withdraw stake");
+ }
+
+ /**
+ * Withdraw from the deposit.
+ * @param withdrawAddress - The address to send withdrawn value.
+ * @param withdrawAmount - The amount to withdraw.
+ */
+ function withdrawTo(
+ address payable withdrawAddress,
+ uint256 withdrawAmount
+ ) external {
+ DepositInfo storage info = deposits[msg.sender];
+ require(withdrawAmount <= info.deposit, "Withdraw amount too large");
+ info.deposit = info.deposit - withdrawAmount;
+ emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);
+ (bool success,) = withdrawAddress.call{value: withdrawAmount}("");
+ require(success, "failed to withdraw");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/UserOperationLib.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/UserOperationLib.sol
new file mode 100644
index 000000000..dcf5740cc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/core/UserOperationLib.sol
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable no-inline-assembly */
+
+import "../interfaces/PackedUserOperation.sol";
+import {calldataKeccak, min} from "./Helpers.sol";
+
+/**
+ * Utility functions helpful when working with UserOperation structs.
+ */
+library UserOperationLib {
+
+ uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;
+ uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;
+ uint256 public constant PAYMASTER_DATA_OFFSET = 52;
+ /**
+ * Get sender from user operation data.
+ * @param userOp - The user operation data.
+ */
+ function getSender(
+ PackedUserOperation calldata userOp
+ ) internal pure returns (address) {
+ address data;
+ //read sender from userOp, which is first userOp member (saves 800 gas...)
+ assembly {
+ data := calldataload(userOp)
+ }
+ return address(uint160(data));
+ }
+
+ /**
+ * Relayer/block builder might submit the TX with higher priorityFee,
+ * but the user should not pay above what he signed for.
+ * @param userOp - The user operation data.
+ */
+ function gasPrice(
+ PackedUserOperation calldata userOp
+ ) internal view returns (uint256) {
+ unchecked {
+ (uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);
+ if (maxFeePerGas == maxPriorityFeePerGas) {
+ //legacy mode (for networks that don't support basefee opcode)
+ return maxFeePerGas;
+ }
+ return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
+ }
+ }
+
+ /**
+ * Pack the user operation data into bytes for hashing.
+ * @param userOp - The user operation data.
+ */
+ function encode(
+ PackedUserOperation calldata userOp
+ ) internal pure returns (bytes memory ret) {
+ address sender = getSender(userOp);
+ uint256 nonce = userOp.nonce;
+ bytes32 hashInitCode = calldataKeccak(userOp.initCode);
+ bytes32 hashCallData = calldataKeccak(userOp.callData);
+ bytes32 accountGasLimits = userOp.accountGasLimits;
+ uint256 preVerificationGas = userOp.preVerificationGas;
+ bytes32 gasFees = userOp.gasFees;
+ bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
+
+ return abi.encode(
+ sender, nonce,
+ hashInitCode, hashCallData,
+ accountGasLimits, preVerificationGas, gasFees,
+ hashPaymasterAndData
+ );
+ }
+
+ function unpackUints(
+ bytes32 packed
+ ) internal pure returns (uint256 high128, uint256 low128) {
+ return (uint128(bytes16(packed)), uint128(uint256(packed)));
+ }
+
+ //unpack just the high 128-bits from a packed value
+ function unpackHigh128(bytes32 packed) internal pure returns (uint256) {
+ return uint256(packed) >> 128;
+ }
+
+ // unpack just the low 128-bits from a packed value
+ function unpackLow128(bytes32 packed) internal pure returns (uint256) {
+ return uint128(uint256(packed));
+ }
+
+ function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)
+ internal pure returns (uint256) {
+ return unpackHigh128(userOp.gasFees);
+ }
+
+ function unpackMaxFeePerGas(PackedUserOperation calldata userOp)
+ internal pure returns (uint256) {
+ return unpackLow128(userOp.gasFees);
+ }
+
+ function unpackVerificationGasLimit(PackedUserOperation calldata userOp)
+ internal pure returns (uint256) {
+ return unpackHigh128(userOp.accountGasLimits);
+ }
+
+ function unpackCallGasLimit(PackedUserOperation calldata userOp)
+ internal pure returns (uint256) {
+ return unpackLow128(userOp.accountGasLimits);
+ }
+
+ function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)
+ internal pure returns (uint256) {
+ return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));
+ }
+
+ function unpackPostOpGasLimit(PackedUserOperation calldata userOp)
+ internal pure returns (uint256) {
+ return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));
+ }
+
+ function unpackPaymasterStaticFields(
+ bytes calldata paymasterAndData
+ ) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {
+ return (
+ address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),
+ uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),
+ uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))
+ );
+ }
+
+ /**
+ * Hash the user operation data.
+ * @param userOp - The user operation data.
+ */
+ function hash(
+ PackedUserOperation calldata userOp
+ ) internal pure returns (bytes32) {
+ return keccak256(encode(userOp));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAccount.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAccount.sol
new file mode 100644
index 000000000..e3b355fbc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAccount.sol
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+import "./PackedUserOperation.sol";
+
+interface IAccount {
+ /**
+ * Validate user's signature and nonce
+ * the entryPoint will make the call to the recipient only if this validation call returns successfully.
+ * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
+ * This allows making a "simulation call" without a valid signature
+ * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
+ *
+ * @dev Must validate caller is the entryPoint.
+ * Must validate the signature and nonce
+ * @param userOp - The operation that is about to be executed.
+ * @param userOpHash - Hash of the user's request data. can be used as the basis for signature.
+ * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.
+ * This is the minimum amount to transfer to the sender(entryPoint) to be
+ * able to make the call. The excess is left as a deposit in the entrypoint
+ * for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()".
+ * In case there is a paymaster in the request (or the current deposit is high
+ * enough), this value will be zero.
+ * @return validationData - Packaged ValidationData structure. use `_packValidationData` and
+ * `_unpackValidationData` to encode and decode.
+ * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
+ * otherwise, an address of an "authorizer" contract.
+ * <6-byte> validUntil - Last timestamp this operation is valid. 0 for "indefinite"
+ * <6-byte> validAfter - First timestamp this operation is valid
+ * If an account doesn't use time-range, it is enough to
+ * return SIG_VALIDATION_FAILED value (1) for signature failure.
+ * Note that the validation code cannot use block.timestamp (or block.number) directly.
+ */
+ function validateUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingAccountFunds
+ ) external returns (uint256 validationData);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAccountExecute.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAccountExecute.sol
new file mode 100644
index 000000000..4433c80ce
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAccountExecute.sol
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+import "./PackedUserOperation.sol";
+
+interface IAccountExecute {
+ /**
+ * Account may implement this execute method.
+ * passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash)
+ * to the account.
+ * The account should skip the methodSig, and use the callData (and optionally, other UserOp fields)
+ *
+ * @param userOp - The operation that was just validated.
+ * @param userOpHash - Hash of the user's request data.
+ */
+ function executeUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash
+ ) external;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAggregator.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAggregator.sol
new file mode 100644
index 000000000..070d8f27a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IAggregator.sol
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+import "./PackedUserOperation.sol";
+
+/**
+ * Aggregated Signatures validator.
+ */
+interface IAggregator {
+ /**
+ * Validate aggregated signature.
+ * Revert if the aggregated signature does not match the given list of operations.
+ * @param userOps - Array of UserOperations to validate the signature for.
+ * @param signature - The aggregated signature.
+ */
+ function validateSignatures(
+ PackedUserOperation[] calldata userOps,
+ bytes calldata signature
+ ) external view;
+
+ /**
+ * Validate signature of a single userOp.
+ * This method should be called by bundler after EntryPointSimulation.simulateValidation() returns
+ * the aggregator this account uses.
+ * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.
+ * @param userOp - The userOperation received from the user.
+ * @return sigForUserOp - The value to put into the signature field of the userOp when calling handleOps.
+ * (usually empty, unless account and aggregator support some kind of "multisig".
+ */
+ function validateUserOpSignature(
+ PackedUserOperation calldata userOp
+ ) external view returns (bytes memory sigForUserOp);
+
+ /**
+ * Aggregate multiple signatures into a single value.
+ * This method is called off-chain to calculate the signature to pass with handleOps()
+ * bundler MAY use optimized custom code perform this aggregation.
+ * @param userOps - Array of UserOperations to collect the signatures from.
+ * @return aggregatedSignature - The aggregated signature.
+ */
+ function aggregateSignatures(
+ PackedUserOperation[] calldata userOps
+ ) external view returns (bytes memory aggregatedSignature);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IEntryPoint.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IEntryPoint.sol
new file mode 100644
index 000000000..28c26f98e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IEntryPoint.sol
@@ -0,0 +1,223 @@
+/**
+ ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
+ ** Only one instance required on each chain.
+ **/
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+/* solhint-disable avoid-low-level-calls */
+/* solhint-disable no-inline-assembly */
+/* solhint-disable reason-string */
+
+import "./PackedUserOperation.sol";
+import "./IStakeManager.sol";
+import "./IAggregator.sol";
+import "./INonceManager.sol";
+
+interface IEntryPoint is IStakeManager, INonceManager {
+ /***
+ * An event emitted after each successful request.
+ * @param userOpHash - Unique identifier for the request (hash its entire content, except signature).
+ * @param sender - The account that generates this request.
+ * @param paymaster - If non-null, the paymaster that pays for this request.
+ * @param nonce - The nonce value from the request.
+ * @param success - True if the sender transaction succeeded, false if reverted.
+ * @param actualGasCost - Actual amount paid (by account or paymaster) for this UserOperation.
+ * @param actualGasUsed - Total gas used by this UserOperation (including preVerification, creation,
+ * validation and execution).
+ */
+ event UserOperationEvent(
+ bytes32 indexed userOpHash,
+ address indexed sender,
+ address indexed paymaster,
+ uint256 nonce,
+ bool success,
+ uint256 actualGasCost,
+ uint256 actualGasUsed
+ );
+
+ /**
+ * Account "sender" was deployed.
+ * @param userOpHash - The userOp that deployed this account. UserOperationEvent will follow.
+ * @param sender - The account that is deployed
+ * @param factory - The factory used to deploy this account (in the initCode)
+ * @param paymaster - The paymaster used by this UserOp
+ */
+ event AccountDeployed(
+ bytes32 indexed userOpHash,
+ address indexed sender,
+ address factory,
+ address paymaster
+ );
+
+ /**
+ * An event emitted if the UserOperation "callData" reverted with non-zero length.
+ * @param userOpHash - The request unique identifier.
+ * @param sender - The sender of this request.
+ * @param nonce - The nonce used in the request.
+ * @param revertReason - The return bytes from the (reverted) call to "callData".
+ */
+ event UserOperationRevertReason(
+ bytes32 indexed userOpHash,
+ address indexed sender,
+ uint256 nonce,
+ bytes revertReason
+ );
+
+ /**
+ * An event emitted if the UserOperation Paymaster's "postOp" call reverted with non-zero length.
+ * @param userOpHash - The request unique identifier.
+ * @param sender - The sender of this request.
+ * @param nonce - The nonce used in the request.
+ * @param revertReason - The return bytes from the (reverted) call to "callData".
+ */
+ event PostOpRevertReason(
+ bytes32 indexed userOpHash,
+ address indexed sender,
+ uint256 nonce,
+ bytes revertReason
+ );
+
+ /**
+ * UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.
+ * @param userOpHash - The request unique identifier.
+ * @param sender - The sender of this request.
+ * @param nonce - The nonce used in the request.
+ */
+ event UserOperationPrefundTooLow(
+ bytes32 indexed userOpHash,
+ address indexed sender,
+ uint256 nonce
+ );
+
+ /**
+ * An event emitted by handleOps(), before starting the execution loop.
+ * Any event emitted before this event, is part of the validation.
+ */
+ event BeforeExecution();
+
+ /**
+ * Signature aggregator used by the following UserOperationEvents within this bundle.
+ * @param aggregator - The aggregator used for the following UserOperationEvents.
+ */
+ event SignatureAggregatorChanged(address indexed aggregator);
+
+ /**
+ * A custom revert error of handleOps, to identify the offending op.
+ * Should be caught in off-chain handleOps simulation and not happen on-chain.
+ * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.
+ * NOTE: If simulateValidation passes successfully, there should be no reason for handleOps to fail on it.
+ * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
+ * @param reason - Revert reason. The string starts with a unique code "AAmn",
+ * where "m" is "1" for factory, "2" for account and "3" for paymaster issues,
+ * so a failure can be attributed to the correct entity.
+ */
+ error FailedOp(uint256 opIndex, string reason);
+
+ /**
+ * A custom revert error of handleOps, to report a revert by account or paymaster.
+ * @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
+ * @param reason - Revert reason. see FailedOp(uint256,string), above
+ * @param inner - data from inner cought revert reason
+ * @dev note that inner is truncated to 2048 bytes
+ */
+ error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);
+
+ error PostOpReverted(bytes returnData);
+
+ /**
+ * Error case when a signature aggregator fails to verify the aggregated signature it had created.
+ * @param aggregator The aggregator that failed to verify the signature
+ */
+ error SignatureValidationFailed(address aggregator);
+
+ // Return value of getSenderAddress.
+ error SenderAddressResult(address sender);
+
+ // UserOps handled, per aggregator.
+ struct UserOpsPerAggregator {
+ PackedUserOperation[] userOps;
+ // Aggregator address
+ IAggregator aggregator;
+ // Aggregated signature
+ bytes signature;
+ }
+
+ /**
+ * Execute a batch of UserOperations.
+ * No signature aggregator is used.
+ * If any account requires an aggregator (that is, it returned an aggregator when
+ * performing simulateValidation), then handleAggregatedOps() must be used instead.
+ * @param ops - The operations to execute.
+ * @param beneficiary - The address to receive the fees.
+ */
+ function handleOps(
+ PackedUserOperation[] calldata ops,
+ address payable beneficiary
+ ) external;
+
+ /**
+ * Execute a batch of UserOperation with Aggregators
+ * @param opsPerAggregator - The operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts).
+ * @param beneficiary - The address to receive the fees.
+ */
+ function handleAggregatedOps(
+ UserOpsPerAggregator[] calldata opsPerAggregator,
+ address payable beneficiary
+ ) external;
+
+ /**
+ * Generate a request Id - unique identifier for this request.
+ * The request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.
+ * @param userOp - The user operation to generate the request ID for.
+ * @return hash the hash of this UserOperation
+ */
+ function getUserOpHash(
+ PackedUserOperation calldata userOp
+ ) external view returns (bytes32);
+
+ /**
+ * Gas and return values during simulation.
+ * @param preOpGas - The gas used for validation (including preValidationGas)
+ * @param prefund - The required prefund for this operation
+ * @param accountValidationData - returned validationData from account.
+ * @param paymasterValidationData - return validationData from paymaster.
+ * @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)
+ */
+ struct ReturnInfo {
+ uint256 preOpGas;
+ uint256 prefund;
+ uint256 accountValidationData;
+ uint256 paymasterValidationData;
+ bytes paymasterContext;
+ }
+
+ /**
+ * Returned aggregated signature info:
+ * The aggregator returned by the account, and its current stake.
+ */
+ struct AggregatorStakeInfo {
+ address aggregator;
+ StakeInfo stakeInfo;
+ }
+
+ /**
+ * Get counterfactual sender address.
+ * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.
+ * This method always revert, and returns the address in SenderAddressResult error
+ * @param initCode - The constructor code to be passed into the UserOperation.
+ */
+ function getSenderAddress(bytes memory initCode) external;
+
+ error DelegateAndRevert(bool success, bytes ret);
+
+ /**
+ * Helper method for dry-run testing.
+ * @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.
+ * The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace
+ * actual EntryPoint code is less convenient.
+ * @param target a target contract to make a delegatecall from entrypoint
+ * @param data data to pass to target in a delegatecall
+ */
+ function delegateAndRevert(address target, bytes calldata data) external;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IEntryPointSimulations.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IEntryPointSimulations.sol
new file mode 100644
index 000000000..a5a894f21
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IEntryPointSimulations.sol
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+import "./PackedUserOperation.sol";
+import "./IEntryPoint.sol";
+
+interface IEntryPointSimulations is IEntryPoint {
+ // Return value of simulateHandleOp.
+ struct ExecutionResult {
+ uint256 preOpGas;
+ uint256 paid;
+ uint256 accountValidationData;
+ uint256 paymasterValidationData;
+ bool targetSuccess;
+ bytes targetResult;
+ }
+
+ /**
+ * Successful result from simulateValidation.
+ * If the account returns a signature aggregator the "aggregatorInfo" struct is filled in as well.
+ * @param returnInfo Gas and time-range returned values
+ * @param senderInfo Stake information about the sender
+ * @param factoryInfo Stake information about the factory (if any)
+ * @param paymasterInfo Stake information about the paymaster (if any)
+ * @param aggregatorInfo Signature aggregation info (if the account requires signature aggregator)
+ * Bundler MUST use it to verify the signature, or reject the UserOperation.
+ */
+ struct ValidationResult {
+ ReturnInfo returnInfo;
+ StakeInfo senderInfo;
+ StakeInfo factoryInfo;
+ StakeInfo paymasterInfo;
+ AggregatorStakeInfo aggregatorInfo;
+ }
+
+ /**
+ * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.
+ * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage
+ * outside the account's data.
+ * @param userOp - The user operation to validate.
+ * @return the validation result structure
+ */
+ function simulateValidation(
+ PackedUserOperation calldata userOp
+ )
+ external
+ returns (
+ ValidationResult memory
+ );
+
+ /**
+ * Simulate full execution of a UserOperation (including both validation and target execution)
+ * It performs full validation of the UserOperation, but ignores signature error.
+ * An optional target address is called after the userop succeeds,
+ * and its value is returned (before the entire call is reverted).
+ * Note that in order to collect the the success/failure of the target call, it must be executed
+ * with trace enabled to track the emitted events.
+ * @param op The UserOperation to simulate.
+ * @param target - If nonzero, a target address to call after userop simulation. If called,
+ * the targetSuccess and targetResult are set to the return from that call.
+ * @param targetCallData - CallData to pass to target address.
+ * @return the execution result structure
+ */
+ function simulateHandleOp(
+ PackedUserOperation calldata op,
+ address target,
+ bytes calldata targetCallData
+ )
+ external
+ returns (
+ ExecutionResult memory
+ );
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/INonceManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/INonceManager.sol
new file mode 100644
index 000000000..2f993f687
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/INonceManager.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+interface INonceManager {
+
+ /**
+ * Return the next nonce for this sender.
+ * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
+ * But UserOp with different keys can come with arbitrary order.
+ *
+ * @param sender the account address
+ * @param key the high 192 bit of the nonce
+ * @return nonce a full nonce to pass for next UserOp with this sender.
+ */
+ function getNonce(address sender, uint192 key)
+ external view returns (uint256 nonce);
+
+ /**
+ * Manually increment the nonce of the sender.
+ * This method is exposed just for completeness..
+ * Account does NOT need to call it, neither during validation, nor elsewhere,
+ * as the EntryPoint will update the nonce regardless.
+ * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future
+ * UserOperations will not pay extra for the first transaction with a given key.
+ */
+ function incrementNonce(uint192 key) external;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IPaymaster.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IPaymaster.sol
new file mode 100644
index 000000000..9176a0b24
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IPaymaster.sol
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+import "./PackedUserOperation.sol";
+
+/**
+ * The interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.
+ * A paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.
+ */
+interface IPaymaster {
+ enum PostOpMode {
+ // User op succeeded.
+ opSucceeded,
+ // User op reverted. Still has to pay for gas.
+ opReverted,
+ // Only used internally in the EntryPoint (cleanup after postOp reverts). Never calling paymaster with this value
+ postOpReverted
+ }
+
+ /**
+ * Payment validation: check if paymaster agrees to pay.
+ * Must verify sender is the entryPoint.
+ * Revert to reject this request.
+ * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted).
+ * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.
+ * @param userOp - The user operation.
+ * @param userOpHash - Hash of the user's request data.
+ * @param maxCost - The maximum cost of this transaction (based on maximum gas and gas price from userOp).
+ * @return context - Value to send to a postOp. Zero length to signify postOp is not required.
+ * @return validationData - Signature and time-range of this operation, encoded the same as the return
+ * value of validateUserOperation.
+ * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
+ * other values are invalid for paymaster.
+ * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite"
+ * <6-byte> validAfter - first timestamp this operation is valid
+ * Note that the validation code cannot use block.timestamp (or block.number) directly.
+ */
+ function validatePaymasterUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 maxCost
+ ) external returns (bytes memory context, uint256 validationData);
+
+ /**
+ * Post-operation handler.
+ * Must verify sender is the entryPoint.
+ * @param mode - Enum with the following options:
+ * opSucceeded - User operation succeeded.
+ * opReverted - User op reverted. The paymaster still has to pay for gas.
+ * postOpReverted - never passed in a call to postOp().
+ * @param context - The context value returned by validatePaymasterUserOp
+ * @param actualGasCost - Actual gas used so far (without this postOp call).
+ * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas
+ * and maxPriorityFee (and basefee)
+ * It is not the same as tx.gasprice, which is what the bundler pays.
+ */
+ function postOp(
+ PostOpMode mode,
+ bytes calldata context,
+ uint256 actualGasCost,
+ uint256 actualUserOpFeePerGas
+ ) external;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IStakeManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IStakeManager.sol
new file mode 100644
index 000000000..69083e93f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/IStakeManager.sol
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-3.0-only
+pragma solidity >=0.7.5;
+
+/**
+ * Manage deposits and stakes.
+ * Deposit is just a balance used to pay for UserOperations (either by a paymaster or an account).
+ * Stake is value locked for at least "unstakeDelay" by the staked entity.
+ */
+interface IStakeManager {
+ event Deposited(address indexed account, uint256 totalDeposit);
+
+ event Withdrawn(
+ address indexed account,
+ address withdrawAddress,
+ uint256 amount
+ );
+
+ // Emitted when stake or unstake delay are modified.
+ event StakeLocked(
+ address indexed account,
+ uint256 totalStaked,
+ uint256 unstakeDelaySec
+ );
+
+ // Emitted once a stake is scheduled for withdrawal.
+ event StakeUnlocked(address indexed account, uint256 withdrawTime);
+
+ event StakeWithdrawn(
+ address indexed account,
+ address withdrawAddress,
+ uint256 amount
+ );
+
+ /**
+ * @param deposit - The entity's deposit.
+ * @param staked - True if this entity is staked.
+ * @param stake - Actual amount of ether staked for this entity.
+ * @param unstakeDelaySec - Minimum delay to withdraw the stake.
+ * @param withdrawTime - First block timestamp where 'withdrawStake' will be callable, or zero if already locked.
+ * @dev Sizes were chosen so that deposit fits into one cell (used during handleOp)
+ * and the rest fit into a 2nd cell (used during stake/unstake)
+ * - 112 bit allows for 10^15 eth
+ * - 48 bit for full timestamp
+ * - 32 bit allows 150 years for unstake delay
+ */
+ struct DepositInfo {
+ uint256 deposit;
+ bool staked;
+ uint112 stake;
+ uint32 unstakeDelaySec;
+ uint48 withdrawTime;
+ }
+
+ // API struct used by getStakeInfo and simulateValidation.
+ struct StakeInfo {
+ uint256 stake;
+ uint256 unstakeDelaySec;
+ }
+
+ /**
+ * Get deposit info.
+ * @param account - The account to query.
+ * @return info - Full deposit information of given account.
+ */
+ function getDepositInfo(
+ address account
+ ) external view returns (DepositInfo memory info);
+
+ /**
+ * Get account balance.
+ * @param account - The account to query.
+ * @return - The deposit (for gas payment) of the account.
+ */
+ function balanceOf(address account) external view returns (uint256);
+
+ /**
+ * Add to the deposit of the given account.
+ * @param account - The account to add to.
+ */
+ function depositTo(address account) external payable;
+
+ /**
+ * Add to the account's stake - amount and delay
+ * any pending unstake is first cancelled.
+ * @param _unstakeDelaySec - The new lock duration before the deposit can be withdrawn.
+ */
+ function addStake(uint32 _unstakeDelaySec) external payable;
+
+ /**
+ * Attempt to unlock the stake.
+ * The value can be withdrawn (using withdrawStake) after the unstake delay.
+ */
+ function unlockStake() external;
+
+ /**
+ * Withdraw from the (unlocked) stake.
+ * Must first call unlockStake and wait for the unstakeDelay to pass.
+ * @param withdrawAddress - The address to send withdrawn value.
+ */
+ function withdrawStake(address payable withdrawAddress) external;
+
+ /**
+ * Withdraw from the deposit.
+ * @param withdrawAddress - The address to send withdrawn value.
+ * @param withdrawAmount - The amount to withdraw.
+ */
+ function withdrawTo(
+ address payable withdrawAddress,
+ uint256 withdrawAmount
+ ) external;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/PackedUserOperation.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/PackedUserOperation.sol
new file mode 100644
index 000000000..fe20de565
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/interfaces/PackedUserOperation.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity >=0.7.5;
+
+/**
+ * User Operation struct
+ * @param sender - The sender account of this request.
+ * @param nonce - Unique value the sender uses to verify it is not a replay.
+ * @param initCode - If set, the account contract will be created by this constructor/
+ * @param callData - The method call to execute on this account.
+ * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
+ * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.
+ * Covers batch overhead.
+ * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
+ * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data
+ * The paymaster will pay for the transaction instead of the sender.
+ * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.
+ */
+struct PackedUserOperation {
+ address sender;
+ uint256 nonce;
+ bytes initCode;
+ bytes callData;
+ bytes32 accountGasLimits;
+ uint256 preVerificationGas;
+ bytes32 gasFees;
+ bytes paymasterAndData;
+ bytes signature;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/package.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/package.json
new file mode 100644
index 000000000..bb1703cb7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "@account-abstraction/contracts",
+ "description": "Account Abstraction (EIP 4337) contracts",
+ "version": "0.7.0",
+ "scripts": {
+ "prepack": "../scripts/prepack-contracts-package.sh",
+ "postpack": "../scripts/postpack-contracts-package.sh"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/eth-infinitism/account-abstraction"
+ },
+ "keywords": [
+ "solidity",
+ "ethereum",
+ "smart",
+ "contracts",
+ "account-abstraction",
+ "erc-4337"
+ ],
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/eth-infinitism/account-abstraction/issues"
+ },
+ "dependencies": {
+ "@openzeppelin/contracts": "^5.0.0",
+ "@uniswap/v3-periphery": "^1.4.3"
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/LegacyTokenPaymaster.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/LegacyTokenPaymaster.sol
new file mode 100644
index 000000000..1589696dd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/LegacyTokenPaymaster.sol
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable reason-string */
+
+import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+import "../core/BasePaymaster.sol";
+import "../core/UserOperationLib.sol";
+import "../core/Helpers.sol";
+
+/**
+ * A sample paymaster that defines itself as a token to pay for gas.
+ * The paymaster IS the token to use, since a paymaster cannot use an external contract.
+ * Also, the exchange rate has to be fixed, since it can't reference an external Uniswap or other exchange contract.
+ * subclass should override "getTokenValueOfEth" to provide actual token exchange rate, settable by the owner.
+ * Known Limitation: this paymaster is exploitable when put into a batch with multiple ops (of different accounts):
+ * - while a single op can't exploit the paymaster (if postOp fails to withdraw the tokens, the user's op is reverted,
+ * and then we know we can withdraw the tokens), multiple ops with different senders (all using this paymaster)
+ * in a batch can withdraw funds from 2nd and further ops, forcing the paymaster itself to pay (from its deposit)
+ * - Possible workarounds are either use a more complex paymaster scheme (e.g. the DepositPaymaster) or
+ * to whitelist the account and the called method ids.
+ */
+contract LegacyTokenPaymaster is BasePaymaster, ERC20 {
+ using UserOperationLib for PackedUserOperation;
+
+ //calculated cost of the postOp
+ uint256 constant public COST_OF_POST = 15000;
+
+ address public immutable theFactory;
+
+ constructor(address accountFactory, string memory _symbol, IEntryPoint _entryPoint) ERC20(_symbol, _symbol) BasePaymaster(_entryPoint) {
+ theFactory = accountFactory;
+ //make it non-empty
+ _mint(address(this), 1);
+
+ //owner is allowed to withdraw tokens from the paymaster's balance
+ _approve(address(this), msg.sender, type(uint256).max);
+ }
+
+
+ /**
+ * helpers for owner, to mint and withdraw tokens.
+ * @param recipient - the address that will receive the minted tokens.
+ * @param amount - the amount it will receive.
+ */
+ function mintTokens(address recipient, uint256 amount) external onlyOwner {
+ _mint(recipient, amount);
+ }
+
+ /**
+ * transfer paymaster ownership.
+ * owner of this paymaster is allowed to withdraw funds (tokens transferred to this paymaster's balance)
+ * when changing owner, the old owner's withdrawal rights are revoked.
+ */
+ function transferOwnership(address newOwner) public override virtual onlyOwner {
+ // remove allowance of current owner
+ _approve(address(this), owner(), 0);
+ super.transferOwnership(newOwner);
+ // new owner is allowed to withdraw tokens from the paymaster's balance
+ _approve(address(this), newOwner, type(uint256).max);
+ }
+
+ //Note: this method assumes a fixed ratio of token-to-eth. subclass should override to supply oracle
+ // or a setter.
+ function getTokenValueOfEth(uint256 valueEth) internal view virtual returns (uint256 valueToken) {
+ return valueEth / 100;
+ }
+
+ /**
+ * validate the request:
+ * if this is a constructor call, make sure it is a known account.
+ * verify the sender has enough tokens.
+ * (since the paymaster is also the token, there is no notion of "approval")
+ */
+ function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 /*userOpHash*/, uint256 requiredPreFund)
+ internal view override returns (bytes memory context, uint256 validationData) {
+ uint256 tokenPrefund = getTokenValueOfEth(requiredPreFund);
+
+ uint256 postOpGasLimit = userOp.unpackPostOpGasLimit();
+ require( postOpGasLimit > COST_OF_POST, "TokenPaymaster: gas too low for postOp");
+
+ if (userOp.initCode.length != 0) {
+ _validateConstructor(userOp);
+ require(balanceOf(userOp.sender) >= tokenPrefund, "TokenPaymaster: no balance (pre-create)");
+ } else {
+
+ require(balanceOf(userOp.sender) >= tokenPrefund, "TokenPaymaster: no balance");
+ }
+
+ return (abi.encode(userOp.sender), SIG_VALIDATION_SUCCESS);
+ }
+
+ // when constructing an account, validate constructor code and parameters
+ // we trust our factory (and that it doesn't have any other public methods)
+ function _validateConstructor(PackedUserOperation calldata userOp) internal virtual view {
+ address factory = address(bytes20(userOp.initCode[0 : 20]));
+ require(factory == theFactory, "TokenPaymaster: wrong account factory");
+ }
+
+ /**
+ * actual charge of user.
+ * this method will be called just after the user's TX with mode==OpSucceeded|OpReverted (account pays in both cases)
+ * BUT: if the user changed its balance in a way that will cause postOp to revert, then it gets called again, after reverting
+ * the user's TX , back to the state it was before the transaction started (before the validatePaymasterUserOp),
+ * and the transaction should succeed there.
+ */
+ function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas) internal override {
+ //we don't really care about the mode, we just pay the gas with the user's tokens.
+ (mode);
+ address sender = abi.decode(context, (address));
+ uint256 charge = getTokenValueOfEth(actualGasCost + COST_OF_POST * actualUserOpFeePerGas);
+ //actualGasCost is known to be no larger than the above requiredPreFund, so the transfer should succeed.
+ _transfer(sender, address(this), charge);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/SimpleAccount.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/SimpleAccount.sol
new file mode 100644
index 000000000..61af6ca6b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/SimpleAccount.sol
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable avoid-low-level-calls */
+/* solhint-disable no-inline-assembly */
+/* solhint-disable reason-string */
+
+import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
+import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
+import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
+import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
+import "../core/BaseAccount.sol";
+import "../core/Helpers.sol";
+import "./callback/TokenCallbackHandler.sol";
+
+/**
+ * minimal account.
+ * this is sample minimal account.
+ * has execute, eth handling methods
+ * has a single signer that can send requests through the entryPoint.
+ */
+contract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, Initializable {
+ address public owner;
+
+ IEntryPoint private immutable _entryPoint;
+
+ event SimpleAccountInitialized(IEntryPoint indexed entryPoint, address indexed owner);
+
+ modifier onlyOwner() {
+ _onlyOwner();
+ _;
+ }
+
+ /// @inheritdoc BaseAccount
+ function entryPoint() public view virtual override returns (IEntryPoint) {
+ return _entryPoint;
+ }
+
+ // solhint-disable-next-line no-empty-blocks
+ receive() external payable {}
+
+ constructor(IEntryPoint anEntryPoint) {
+ _entryPoint = anEntryPoint;
+ _disableInitializers();
+ }
+
+ function _onlyOwner() internal view {
+ //directly from EOA owner, or through the account itself (which gets redirected through execute())
+ require(msg.sender == owner || msg.sender == address(this), "only owner");
+ }
+
+ /**
+ * execute a transaction (called directly from owner, or by entryPoint)
+ * @param dest destination address to call
+ * @param value the value to pass in this call
+ * @param func the calldata to pass in this call
+ */
+ function execute(address dest, uint256 value, bytes calldata func) external {
+ _requireFromEntryPointOrOwner();
+ _call(dest, value, func);
+ }
+
+ /**
+ * execute a sequence of transactions
+ * @dev to reduce gas consumption for trivial case (no value), use a zero-length array to mean zero value
+ * @param dest an array of destination addresses
+ * @param value an array of values to pass to each call. can be zero-length for no-value calls
+ * @param func an array of calldata to pass to each call
+ */
+ function executeBatch(address[] calldata dest, uint256[] calldata value, bytes[] calldata func) external {
+ _requireFromEntryPointOrOwner();
+ require(dest.length == func.length && (value.length == 0 || value.length == func.length), "wrong array lengths");
+ if (value.length == 0) {
+ for (uint256 i = 0; i < dest.length; i++) {
+ _call(dest[i], 0, func[i]);
+ }
+ } else {
+ for (uint256 i = 0; i < dest.length; i++) {
+ _call(dest[i], value[i], func[i]);
+ }
+ }
+ }
+
+ /**
+ * @dev The _entryPoint member is immutable, to reduce gas consumption. To upgrade EntryPoint,
+ * a new implementation of SimpleAccount must be deployed with the new EntryPoint address, then upgrading
+ * the implementation by calling `upgradeTo()`
+ * @param anOwner the owner (signer) of this account
+ */
+ function initialize(address anOwner) public virtual initializer {
+ _initialize(anOwner);
+ }
+
+ function _initialize(address anOwner) internal virtual {
+ owner = anOwner;
+ emit SimpleAccountInitialized(_entryPoint, owner);
+ }
+
+ // Require the function call went through EntryPoint or owner
+ function _requireFromEntryPointOrOwner() internal view {
+ require(msg.sender == address(entryPoint()) || msg.sender == owner, "account: not Owner or EntryPoint");
+ }
+
+ /// implement template method of BaseAccount
+ function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)
+ internal override virtual returns (uint256 validationData) {
+ bytes32 hash = MessageHashUtils.toEthSignedMessageHash(userOpHash);
+ if (owner != ECDSA.recover(hash, userOp.signature))
+ return SIG_VALIDATION_FAILED;
+ return SIG_VALIDATION_SUCCESS;
+ }
+
+ function _call(address target, uint256 value, bytes memory data) internal {
+ (bool success, bytes memory result) = target.call{value: value}(data);
+ if (!success) {
+ assembly {
+ revert(add(result, 32), mload(result))
+ }
+ }
+ }
+
+ /**
+ * check current account deposit in the entryPoint
+ */
+ function getDeposit() public view returns (uint256) {
+ return entryPoint().balanceOf(address(this));
+ }
+
+ /**
+ * deposit more funds for this account in the entryPoint
+ */
+ function addDeposit() public payable {
+ entryPoint().depositTo{value: msg.value}(address(this));
+ }
+
+ /**
+ * withdraw value from the account's deposit
+ * @param withdrawAddress target to send to
+ * @param amount to withdraw
+ */
+ function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner {
+ entryPoint().withdrawTo(withdrawAddress, amount);
+ }
+
+ function _authorizeUpgrade(address newImplementation) internal view override {
+ (newImplementation);
+ _onlyOwner();
+ }
+}
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/SimpleAccountFactory.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/SimpleAccountFactory.sol
new file mode 100644
index 000000000..5afa2ce60
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/SimpleAccountFactory.sol
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+import "@openzeppelin/contracts/utils/Create2.sol";
+import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+
+import "./SimpleAccount.sol";
+
+/**
+ * A sample factory contract for SimpleAccount
+ * A UserOperations "initCode" holds the address of the factory, and a method call (to createAccount, in this sample factory).
+ * The factory's createAccount returns the target account address even if it is already installed.
+ * This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.
+ */
+contract SimpleAccountFactory {
+ SimpleAccount public immutable accountImplementation;
+
+ constructor(IEntryPoint _entryPoint) {
+ accountImplementation = new SimpleAccount(_entryPoint);
+ }
+
+ /**
+ * create an account, and return its address.
+ * returns the address even if the account is already deployed.
+ * Note that during UserOperation execution, this method is called only if the account is not deployed.
+ * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation
+ */
+ function createAccount(address owner,uint256 salt) public returns (SimpleAccount ret) {
+ address addr = getAddress(owner, salt);
+ uint256 codeSize = addr.code.length;
+ if (codeSize > 0) {
+ return SimpleAccount(payable(addr));
+ }
+ ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(
+ address(accountImplementation),
+ abi.encodeCall(SimpleAccount.initialize, (owner))
+ )));
+ }
+
+ /**
+ * calculate the counterfactual address of this account as it would be returned by createAccount()
+ */
+ function getAddress(address owner,uint256 salt) public view returns (address) {
+ return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(
+ type(ERC1967Proxy).creationCode,
+ abi.encode(
+ address(accountImplementation),
+ abi.encodeCall(SimpleAccount.initialize, (owner))
+ )
+ )));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/TokenPaymaster.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/TokenPaymaster.sol
new file mode 100644
index 000000000..1d4c50d63
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/TokenPaymaster.sol
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+// Import the required libraries and contracts
+import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
+import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
+
+import "../interfaces/IEntryPoint.sol";
+import "../core/BasePaymaster.sol";
+import "../core/Helpers.sol";
+import "./utils/UniswapHelper.sol";
+import "./utils/OracleHelper.sol";
+
+/// @title Sample ERC-20 Token Paymaster for ERC-4337
+/// This Paymaster covers gas fees in exchange for ERC20 tokens charged using allowance pre-issued by ERC-4337 accounts.
+/// The contract refunds excess tokens if the actual gas cost is lower than the initially provided amount.
+/// The token price cannot be queried in the validation code due to storage access restrictions of ERC-4337.
+/// The price is cached inside the contract and is updated in the 'postOp' stage if the change is >10%.
+/// It is theoretically possible the token has depreciated so much since the last 'postOp' the refund becomes negative.
+/// The contract reverts the inner user transaction in that case but keeps the charge.
+/// The contract also allows honest clients to prepay tokens at a higher price to avoid getting reverted.
+/// It also allows updating price configuration and withdrawing tokens by the contract owner.
+/// The contract uses an Oracle to fetch the latest token prices.
+/// @dev Inherits from BasePaymaster.
+contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper {
+
+ using UserOperationLib for PackedUserOperation;
+
+ struct TokenPaymasterConfig {
+ /// @notice The price markup percentage applied to the token price (1e26 = 100%). Ranges from 1e26 to 2e26
+ uint256 priceMarkup;
+
+ /// @notice Exchange tokens to native currency if the EntryPoint balance of this Paymaster falls below this value
+ uint128 minEntryPointBalance;
+
+ /// @notice Estimated gas cost for refunding tokens after the transaction is completed
+ uint48 refundPostopCost;
+
+ /// @notice Transactions are only valid as long as the cached price is not older than this value
+ uint48 priceMaxAge;
+ }
+
+ event ConfigUpdated(TokenPaymasterConfig tokenPaymasterConfig);
+
+ event UserOperationSponsored(address indexed user, uint256 actualTokenCharge, uint256 actualGasCost, uint256 actualTokenPriceWithMarkup);
+
+ event Received(address indexed sender, uint256 value);
+
+ /// @notice All 'price' variables are multiplied by this value to avoid rounding up
+ uint256 private constant PRICE_DENOMINATOR = 1e26;
+
+ TokenPaymasterConfig public tokenPaymasterConfig;
+
+ /// @notice Initializes the TokenPaymaster contract with the given parameters.
+ /// @param _token The ERC20 token used for transaction fee payments.
+ /// @param _entryPoint The EntryPoint contract used in the Account Abstraction infrastructure.
+ /// @param _wrappedNative The ERC-20 token that wraps the native asset for current chain.
+ /// @param _uniswap The Uniswap V3 SwapRouter contract.
+ /// @param _tokenPaymasterConfig The configuration for the Token Paymaster.
+ /// @param _oracleHelperConfig The configuration for the Oracle Helper.
+ /// @param _uniswapHelperConfig The configuration for the Uniswap Helper.
+ /// @param _owner The address that will be set as the owner of the contract.
+ constructor(
+ IERC20Metadata _token,
+ IEntryPoint _entryPoint,
+ IERC20 _wrappedNative,
+ ISwapRouter _uniswap,
+ TokenPaymasterConfig memory _tokenPaymasterConfig,
+ OracleHelperConfig memory _oracleHelperConfig,
+ UniswapHelperConfig memory _uniswapHelperConfig,
+ address _owner
+ )
+ BasePaymaster(
+ _entryPoint
+ )
+ OracleHelper(
+ _oracleHelperConfig
+ )
+ UniswapHelper(
+ _token,
+ _wrappedNative,
+ _uniswap,
+ _uniswapHelperConfig
+ )
+ {
+ setTokenPaymasterConfig(_tokenPaymasterConfig);
+ transferOwnership(_owner);
+ }
+
+ /// @notice Updates the configuration for the Token Paymaster.
+ /// @param _tokenPaymasterConfig The new configuration struct.
+ function setTokenPaymasterConfig(
+ TokenPaymasterConfig memory _tokenPaymasterConfig
+ ) public onlyOwner {
+ require(_tokenPaymasterConfig.priceMarkup <= 2 * PRICE_DENOMINATOR, "TPM: price markup too high");
+ require(_tokenPaymasterConfig.priceMarkup >= PRICE_DENOMINATOR, "TPM: price markup too low");
+ tokenPaymasterConfig = _tokenPaymasterConfig;
+ emit ConfigUpdated(_tokenPaymasterConfig);
+ }
+
+ function setUniswapConfiguration(
+ UniswapHelperConfig memory _uniswapHelperConfig
+ ) external onlyOwner {
+ _setUniswapHelperConfiguration(_uniswapHelperConfig);
+ }
+
+ /// @notice Allows the contract owner to withdraw a specified amount of tokens from the contract.
+ /// @param to The address to transfer the tokens to.
+ /// @param amount The amount of tokens to transfer.
+ function withdrawToken(address to, uint256 amount) external onlyOwner {
+ SafeERC20.safeTransfer(token, to, amount);
+ }
+
+ /// @notice Validates a paymaster user operation and calculates the required token amount for the transaction.
+ /// @param userOp The user operation data.
+ /// @param requiredPreFund The maximum cost (in native token) the paymaster has to prefund.
+ /// @return context The context containing the token amount and user sender address (if applicable).
+ /// @return validationResult A uint256 value indicating the result of the validation (always 0 in this implementation).
+ function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32, uint256 requiredPreFund)
+ internal
+ override
+ returns (bytes memory context, uint256 validationResult) {unchecked {
+ uint256 priceMarkup = tokenPaymasterConfig.priceMarkup;
+ uint256 dataLength = userOp.paymasterAndData.length - PAYMASTER_DATA_OFFSET;
+ require(dataLength == 0 || dataLength == 32,
+ "TPM: invalid data length"
+ );
+ uint256 maxFeePerGas = userOp.unpackMaxFeePerGas();
+ uint256 refundPostopCost = tokenPaymasterConfig.refundPostopCost;
+ require(refundPostopCost < userOp.unpackPostOpGasLimit(), "TPM: postOpGasLimit too low");
+ uint256 preChargeNative = requiredPreFund + (refundPostopCost * maxFeePerGas);
+ // note: as price is in native-asset-per-token and we want more tokens increasing it means dividing it by markup
+ uint256 cachedPriceWithMarkup = cachedPrice * PRICE_DENOMINATOR / priceMarkup;
+ if (dataLength == 32) {
+ uint256 clientSuppliedPrice = uint256(bytes32(userOp.paymasterAndData[PAYMASTER_DATA_OFFSET : PAYMASTER_DATA_OFFSET + 32]));
+ if (clientSuppliedPrice < cachedPriceWithMarkup) {
+ // note: smaller number means 'more native asset per token'
+ cachedPriceWithMarkup = clientSuppliedPrice;
+ }
+ }
+ uint256 tokenAmount = weiToToken(preChargeNative, cachedPriceWithMarkup);
+ SafeERC20.safeTransferFrom(token, userOp.sender, address(this), tokenAmount);
+ context = abi.encode(tokenAmount, userOp.sender);
+ validationResult = _packValidationData(
+ false,
+ uint48(cachedPriceTimestamp + tokenPaymasterConfig.priceMaxAge),
+ 0
+ );
+ }
+ }
+
+ /// @notice Performs post-operation tasks, such as updating the token price and refunding excess tokens.
+ /// @dev This function is called after a user operation has been executed or reverted.
+ /// @param context The context containing the token amount and user sender address.
+ /// @param actualGasCost The actual gas cost of the transaction.
+ /// @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas
+ // and maxPriorityFee (and basefee)
+ // It is not the same as tx.gasprice, which is what the bundler pays.
+ function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas) internal override {
+ unchecked {
+ uint256 priceMarkup = tokenPaymasterConfig.priceMarkup;
+ (
+ uint256 preCharge,
+ address userOpSender
+ ) = abi.decode(context, (uint256, address));
+ uint256 _cachedPrice = updateCachedPrice(false);
+ // note: as price is in native-asset-per-token and we want more tokens increasing it means dividing it by markup
+ uint256 cachedPriceWithMarkup = _cachedPrice * PRICE_DENOMINATOR / priceMarkup;
+ // Refund tokens based on actual gas cost
+ uint256 actualChargeNative = actualGasCost + tokenPaymasterConfig.refundPostopCost * actualUserOpFeePerGas;
+ uint256 actualTokenNeeded = weiToToken(actualChargeNative, cachedPriceWithMarkup);
+ if (preCharge > actualTokenNeeded) {
+ // If the initially provided token amount is greater than the actual amount needed, refund the difference
+ SafeERC20.safeTransfer(
+ token,
+ userOpSender,
+ preCharge - actualTokenNeeded
+ );
+ } else if (preCharge < actualTokenNeeded) {
+ // Attempt to cover Paymaster's gas expenses by withdrawing the 'overdraft' from the client
+ // If the transfer reverts also revert the 'postOp' to remove the incentive to cheat
+ SafeERC20.safeTransferFrom(
+ token,
+ userOpSender,
+ address(this),
+ actualTokenNeeded - preCharge
+ );
+ }
+
+ emit UserOperationSponsored(userOpSender, actualTokenNeeded, actualGasCost, cachedPriceWithMarkup);
+ refillEntryPointDeposit(_cachedPrice);
+ }
+ }
+
+ /// @notice If necessary this function uses this Paymaster's token balance to refill the deposit on EntryPoint
+ /// @param _cachedPrice the token price that will be used to calculate the swap amount.
+ function refillEntryPointDeposit(uint256 _cachedPrice) private {
+ uint256 currentEntryPointBalance = entryPoint.balanceOf(address(this));
+ if (
+ currentEntryPointBalance < tokenPaymasterConfig.minEntryPointBalance
+ ) {
+ uint256 swappedWeth = _maybeSwapTokenToWeth(token, _cachedPrice);
+ unwrapWeth(swappedWeth);
+ entryPoint.depositTo{value: address(this).balance}(address(this));
+ }
+ }
+
+ receive() external payable {
+ emit Received(msg.sender, msg.value);
+ }
+
+ function withdrawEth(address payable recipient, uint256 amount) external onlyOwner {
+ (bool success,) = recipient.call{value: amount}("");
+ require(success, "withdraw failed");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/VerifyingPaymaster.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/VerifyingPaymaster.sol
new file mode 100644
index 000000000..1ddce2f47
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/VerifyingPaymaster.sol
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable reason-string */
+/* solhint-disable no-inline-assembly */
+
+import "../core/BasePaymaster.sol";
+import "../core/UserOperationLib.sol";
+import "../core/Helpers.sol";
+import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
+import "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
+/**
+ * A sample paymaster that uses external service to decide whether to pay for the UserOp.
+ * The paymaster trusts an external signer to sign the transaction.
+ * The calling user must pass the UserOp to that external signer first, which performs
+ * whatever off-chain verification before signing the UserOp.
+ * Note that this signature is NOT a replacement for the account-specific signature:
+ * - the paymaster checks a signature to agree to PAY for GAS.
+ * - the account checks a signature to prove identity and account ownership.
+ */
+contract VerifyingPaymaster is BasePaymaster {
+
+ using UserOperationLib for PackedUserOperation;
+
+ address public immutable verifyingSigner;
+
+ uint256 private constant VALID_TIMESTAMP_OFFSET = PAYMASTER_DATA_OFFSET;
+
+ uint256 private constant SIGNATURE_OFFSET = VALID_TIMESTAMP_OFFSET + 64;
+
+ constructor(IEntryPoint _entryPoint, address _verifyingSigner) BasePaymaster(_entryPoint) {
+ verifyingSigner = _verifyingSigner;
+ }
+
+ /**
+ * return the hash we're going to sign off-chain (and validate on-chain)
+ * this method is called by the off-chain service, to sign the request.
+ * it is called on-chain from the validatePaymasterUserOp, to validate the signature.
+ * note that this signature covers all fields of the UserOperation, except the "paymasterAndData",
+ * which will carry the signature itself.
+ */
+ function getHash(PackedUserOperation calldata userOp, uint48 validUntil, uint48 validAfter)
+ public view returns (bytes32) {
+ //can't use userOp.hash(), since it contains also the paymasterAndData itself.
+ address sender = userOp.getSender();
+ return
+ keccak256(
+ abi.encode(
+ sender,
+ userOp.nonce,
+ keccak256(userOp.initCode),
+ keccak256(userOp.callData),
+ userOp.accountGasLimits,
+ uint256(bytes32(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_DATA_OFFSET])),
+ userOp.preVerificationGas,
+ userOp.gasFees,
+ block.chainid,
+ address(this),
+ validUntil,
+ validAfter
+ )
+ );
+ }
+
+ /**
+ * verify our external signer signed this request.
+ * the "paymasterAndData" is expected to be the paymaster and a signature over the entire request params
+ * paymasterAndData[:20] : address(this)
+ * paymasterAndData[20:84] : abi.encode(validUntil, validAfter)
+ * paymasterAndData[84:] : signature
+ */
+ function _validatePaymasterUserOp(PackedUserOperation calldata userOp, bytes32 /*userOpHash*/, uint256 requiredPreFund)
+ internal view override returns (bytes memory context, uint256 validationData) {
+ (requiredPreFund);
+
+ (uint48 validUntil, uint48 validAfter, bytes calldata signature) = parsePaymasterAndData(userOp.paymasterAndData);
+ //ECDSA library supports both 64 and 65-byte long signatures.
+ // we only "require" it here so that the revert reason on invalid signature will be of "VerifyingPaymaster", and not "ECDSA"
+ require(signature.length == 64 || signature.length == 65, "VerifyingPaymaster: invalid signature length in paymasterAndData");
+ bytes32 hash = MessageHashUtils.toEthSignedMessageHash(getHash(userOp, validUntil, validAfter));
+
+ //don't revert on signature failure: return SIG_VALIDATION_FAILED
+ if (verifyingSigner != ECDSA.recover(hash, signature)) {
+ return ("", _packValidationData(true, validUntil, validAfter));
+ }
+
+ //no need for other on-chain validation: entire UserOp should have been checked
+ // by the external service prior to signing it.
+ return ("", _packValidationData(false, validUntil, validAfter));
+ }
+
+ function parsePaymasterAndData(bytes calldata paymasterAndData) public pure returns (uint48 validUntil, uint48 validAfter, bytes calldata signature) {
+ (validUntil, validAfter) = abi.decode(paymasterAndData[VALID_TIMESTAMP_OFFSET :], (uint48, uint48));
+ signature = paymasterAndData[SIGNATURE_OFFSET :];
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSAccount.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSAccount.sol
new file mode 100644
index 000000000..cd480a792
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSAccount.sol
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+import "../SimpleAccount.sol";
+import "./IBLSAccount.sol";
+import "../../core/Helpers.sol";
+
+/**
+ * Minimal BLS-based account that uses an aggregated signature.
+ * The account must maintain its own BLS public key, and expose its trusted signature aggregator.
+ * Note that unlike the "standard" SimpleAccount, this account can't be called directly
+ * (normal SimpleAccount uses its "signer" address as both the ecrecover signer, and as a legitimate
+ * Ethereum sender address. Obviously, a BLS public key is not a valid Ethereum sender address.)
+ */
+contract BLSAccount is SimpleAccount, IBLSAccount {
+ address public immutable aggregator;
+ uint256[4] private publicKey;
+
+ // The constructor is used only for the "implementation" and only sets immutable values.
+ // Mutable value slots for proxy accounts are set by the 'initialize' function.
+ constructor(IEntryPoint anEntryPoint, address anAggregator) SimpleAccount(anEntryPoint) {
+ aggregator = anAggregator;
+ }
+
+ /**
+ * The initializer for the BLSAccount instance.
+ * @param aPublicKey public key from a BLS keypair that will have a full ownership and control of this account.
+ */
+ function initialize(uint256[4] memory aPublicKey) public virtual initializer {
+ super._initialize(address(0));
+ _setBlsPublicKey(aPublicKey);
+ }
+
+ function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)
+ internal override view returns (uint256 validationData) {
+
+ (userOp, userOpHash);
+ if (userOp.initCode.length != 0) {
+ // BLSSignatureAggregator.getUserOpPublicKey() assumes that during account creation, the public key is
+ // the suffix of the initCode.
+ // The account MUST validate it
+ bytes32 pubKeyHash = keccak256(abi.encode(getBlsPublicKey()));
+ require(keccak256(userOp.initCode[userOp.initCode.length - 128 :]) == pubKeyHash, "wrong pubkey");
+ }
+ return _packValidationData(ValidationData(aggregator, 0,0));
+ }
+
+ /**
+ * Allows the owner to set or change the BLS key.
+ * @param newPublicKey public key from a BLS keypair that will have a full ownership and control of this account.
+ */
+ function setBlsPublicKey(uint256[4] memory newPublicKey) public onlyOwner {
+ _setBlsPublicKey(newPublicKey);
+ }
+
+ function _setBlsPublicKey(uint256[4] memory newPublicKey) internal {
+ emit PublicKeyChanged(publicKey, newPublicKey);
+ publicKey = newPublicKey;
+ }
+
+ /// @inheritdoc IBLSAccount
+ function getBlsPublicKey() public override view returns (uint256[4] memory) {
+ return publicKey;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSAccountFactory.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSAccountFactory.sol
new file mode 100644
index 000000000..95947142f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSAccountFactory.sol
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+import "@openzeppelin/contracts/utils/Create2.sol";
+import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+
+import "../../interfaces/IEntryPoint.sol";
+import "./BLSAccount.sol";
+
+/* solhint-disable no-inline-assembly */
+
+/**
+ * Based on SimpleAccountFactory.
+ * Cannot be a subclass since both constructor and createAccount depend on the
+ * constructor and initializer of the actual account contract.
+ */
+contract BLSAccountFactory {
+ BLSAccount public immutable accountImplementation;
+
+ constructor(IEntryPoint entryPoint, address aggregator){
+ accountImplementation = new BLSAccount(entryPoint, aggregator);
+ }
+
+ /**
+ * create an account, and return its address.
+ * returns the address even if the account is already deployed.
+ * Note that during UserOperation execution, this method is called only if the account is not deployed.
+ * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation
+ * Also note that our BLSSignatureAggregator requires that the public key is the last parameter
+ */
+ function createAccount(uint256 salt, uint256[4] calldata aPublicKey) public returns (BLSAccount) {
+
+ // the BLSSignatureAggregator depends on the public-key being the last 4 uint256 of msg.data.
+ uint256 slot;
+ assembly {slot := aPublicKey}
+ require(slot == msg.data.length - 128, "wrong pubkey offset");
+
+ address addr = getAddress(salt, aPublicKey);
+ uint256 codeSize = addr.code.length;
+ if (codeSize > 0) {
+ return BLSAccount(payable(addr));
+ }
+ return BLSAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(
+ address(accountImplementation),
+ abi.encodeCall(BLSAccount.initialize, aPublicKey)
+ )));
+ }
+
+ /**
+ * calculate the counterfactual address of this account as it would be returned by createAccount()
+ */
+ function getAddress(uint256 salt, uint256[4] memory aPublicKey) public view returns (address) {
+ return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(
+ type(ERC1967Proxy).creationCode,
+ abi.encode(
+ address(accountImplementation),
+ abi.encodeCall(BLSAccount.initialize, (aPublicKey))
+ )
+ )));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSHelper.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSHelper.sol
new file mode 100644
index 000000000..a1a197134
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSHelper.sol
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+// code taken from : https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol
+// missing core functions from "thehubbleproject/bls": jacAdd (and sum)
+library BLSHelper {
+
+ struct XY {
+ uint256 x;
+ uint256 y;
+ }
+ /**
+ * sum all the points in the array
+ * NOTE: the "ecAdd" (below) has a special case where x1==y2.
+ * @param points an array of bytes32[2], representing an (x,y) of a point
+ * @param _pp the modulus of the curve
+ * @return ret the sum of all points
+ */
+ function sum(XY[] memory points, uint256 _pp) internal pure returns (XY memory ret){
+ uint256 x = points[0].x;
+ uint256 y = points[0].y;
+ uint256 z = 1;
+
+ for (uint256 i = 1; i < points.length; i++) {
+ (x, y, z) = jacAdd(x, y, z, points[i].x, points[i].y, 1, _pp);
+ }
+ (x, y) = toAffine(x, y, z, _pp);
+ ret.x = x;
+ ret.y = y;
+ }
+
+ /// @dev Adds two points (x1, y1, z1) and (x2, y2, z2).
+ /// @param _x1 coordinate x of P1
+ /// @param _y1 coordinate y of P1
+ /// @param _z1 coordinate z of P1
+ /// @param _x2 coordinate x of square
+ /// @param _y2 coordinate y of square
+ /// @param _z2 coordinate z of square
+ /// @param _pp the modulus
+ /// @return (qx, qy, qz) P1+square in Jacobian
+ function jacAdd(
+ uint256 _x1,
+ uint256 _y1,
+ uint256 _z1,
+ uint256 _x2,
+ uint256 _y2,
+ uint256 _z2,
+ uint256 _pp)
+ internal pure returns (uint256, uint256, uint256)
+ {
+ if (_x1 == 0 && _y1 == 0)
+ return (_x2, _y2, _z2);
+ if (_x2 == 0 && _y2 == 0)
+ return (_x1, _y1, _z1);
+
+ // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5
+ uint256[4] memory zs;
+ // z1^2, z1^3, z2^2, z2^3
+ zs[0] = mulmod(_z1, _z1, _pp);
+ zs[1] = mulmod(_z1, zs[0], _pp);
+ zs[2] = mulmod(_z2, _z2, _pp);
+ zs[3] = mulmod(_z2, zs[2], _pp);
+
+ // u1, s1, u2, s2
+ zs = [
+ mulmod(_x1, zs[2], _pp),
+ mulmod(_y1, zs[3], _pp),
+ mulmod(_x2, zs[0], _pp),
+ mulmod(_y2, zs[1], _pp)
+ ];
+
+ // In case of zs[0] == zs[2] && zs[1] == zs[3], double function should be used
+ require(zs[0] != zs[2] || zs[1] != zs[3], "Use jacDouble function instead");
+
+ uint256[4] memory hr;
+ //h
+ hr[0] = addmod(zs[2], _pp - zs[0], _pp);
+ //r
+ hr[1] = addmod(zs[3], _pp - zs[1], _pp);
+ //h^2
+ hr[2] = mulmod(hr[0], hr[0], _pp);
+ // h^3
+ hr[3] = mulmod(hr[2], hr[0], _pp);
+ // qx = -h^3 -2u1h^2+r^2
+ uint256 qx = addmod(mulmod(hr[1], hr[1], _pp), _pp - hr[3], _pp);
+ qx = addmod(qx, _pp - mulmod(2, mulmod(zs[0], hr[2], _pp), _pp), _pp);
+ // qy = -s1*z1*h^3+r(u1*h^2 -x^3)
+ uint256 qy = mulmod(hr[1], addmod(mulmod(zs[0], hr[2], _pp), _pp - qx, _pp), _pp);
+ qy = addmod(qy, _pp - mulmod(zs[1], hr[3], _pp), _pp);
+ // qz = h*z1*z2
+ uint256 qz = mulmod(hr[0], mulmod(_z1, _z2, _pp), _pp);
+ return (qx, qy, qz);
+ }
+
+
+ /// @dev Converts a point (x, y, z) expressed in Jacobian coordinates to affine coordinates (x', y', 1).
+ /// @param _x coordinate x
+ /// @param _y coordinate y
+ /// @param _z coordinate z
+ /// @param _pp the modulus
+ /// @return (x', y') affine coordinates
+ function toAffine(
+ uint256 _x,
+ uint256 _y,
+ uint256 _z,
+ uint256 _pp)
+ internal pure returns (uint256, uint256)
+ {
+ uint256 zInv = invMod(_z, _pp);
+ uint256 zInv2 = mulmod(zInv, zInv, _pp);
+ uint256 x2 = mulmod(_x, zInv2, _pp);
+ uint256 y2 = mulmod(_y, mulmod(zInv, zInv2, _pp), _pp);
+
+ return (x2, y2);
+ }
+
+
+ /// @dev Modular euclidean inverse of a number (mod p).
+ /// @param _x The number
+ /// @param _pp The modulus
+ /// @return q such that x*q = 1 (mod _pp)
+ function invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) {
+ require(_x != 0 && _x != _pp && _pp != 0, "Invalid number");
+ uint256 q = 0;
+ uint256 newT = 1;
+ uint256 r = _pp;
+ uint256 t;
+ while (_x != 0) {
+ t = r / _x;
+ (q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp));
+ (r, _x) = (_x, r - t * _x);
+ }
+
+ return q;
+ }
+
+ /// @dev Doubles a point (x, y, z).
+ /// @param _x coordinate x of P1
+ /// @param _y coordinate y of P1
+ /// @param _z coordinate z of P1
+ /// @param _aa the a scalar in the curve equation
+ /// @param _pp the modulus
+ /// @return (qx, qy, qz) 2P in Jacobian
+ function jacDouble(
+ uint256 _x,
+ uint256 _y,
+ uint256 _z,
+ uint256 _aa,
+ uint256 _pp)
+ internal pure returns (uint256, uint256, uint256)
+ {
+ if (_z == 0)
+ return (_x, _y, _z);
+
+ // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5
+ // Note: there is a bug in the paper regarding the m parameter, M=3*(x1^2)+a*(z1^4)
+ // x, y, z at this point represent the squares of _x, _y, _z
+ uint256 x = mulmod(_x, _x, _pp); //x1^2
+ uint256 y = mulmod(_y, _y, _pp); //y1^2
+ uint256 z = mulmod(_z, _z, _pp); //z1^2
+
+ // s
+ uint256 s = mulmod(4, mulmod(_x, y, _pp), _pp);
+ // m
+ uint256 m = addmod(mulmod(3, x, _pp), mulmod(_aa, mulmod(z, z, _pp), _pp), _pp);
+
+ // x, y, z at this point will be reassigned and rather represent qx, qy, qz from the paper
+ // This allows to reduce the gas cost and stack footprint of the algorithm
+ // qx
+ x = addmod(mulmod(m, m, _pp), _pp - addmod(s, s, _pp), _pp);
+ // qy = -8*y1^4 + M(S-T)
+ y = addmod(mulmod(m, addmod(s, _pp - x, _pp), _pp), _pp - mulmod(8, mulmod(y, y, _pp), _pp), _pp);
+ // qz = 2*y1*z1
+ z = mulmod(2, mulmod(_y, _z, _pp), _pp);
+
+ return (x, y, z);
+ }
+
+ /// @dev Add two points (x1, y1) and (x2, y2) in affine coordinates.
+ /// @param _x1 coordinate x of P1
+ /// @param _y1 coordinate y of P1
+ /// @param _x2 coordinate x of P2
+ /// @param _y2 coordinate y of P2
+ /// @param _aa constant of the curve
+ /// @param _pp the modulus
+ /// @return (qx, qy) = P1+P2 in affine coordinates
+ function ecAdd(
+ uint256 _x1,
+ uint256 _y1,
+ uint256 _x2,
+ uint256 _y2,
+ uint256 _aa,
+ uint256 _pp)
+ internal pure returns (uint256, uint256)
+ {
+ uint256 x = 0;
+ uint256 y = 0;
+ uint256 z = 0;
+
+ // Double if x1==x2 else add
+ if (_x1 == _x2) {
+ // y1 = -y2 mod p
+ if (addmod(_y1, _y2, _pp) == 0) {
+ return (0, 0);
+ } else {
+ // P1 = P2
+ (x, y, z) = jacDouble(
+ _x1,
+ _y1,
+ 1,
+ _aa,
+ _pp);
+ }
+ } else {
+ (x, y, z) = jacAdd(
+ _x1,
+ _y1,
+ 1,
+ _x2,
+ _y2,
+ 1,
+ _pp);
+ }
+ // Get back to affine
+ return toAffine(
+ x,
+ y,
+ z,
+ _pp);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSSignatureAggregator.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSSignatureAggregator.sol
new file mode 100644
index 000000000..a2ac0f325
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/BLSSignatureAggregator.sol
@@ -0,0 +1,171 @@
+//SPDX-License-Identifier: Unlicense
+pragma solidity ^0.8.23;
+
+import "../../interfaces/IAggregator.sol";
+import "../../interfaces/IEntryPoint.sol";
+import "../../core/UserOperationLib.sol";
+import {BLSOpen} from "./lib/BLSOpen.sol";
+import "./IBLSAccount.sol";
+import "./BLSHelper.sol";
+
+/**
+ * A BLS-based signature aggregator, to validate aggregated signature of multiple UserOps if BLSAccount
+ */
+contract BLSSignatureAggregator is IAggregator {
+ using UserOperationLib for PackedUserOperation;
+
+ bytes32 public constant BLS_DOMAIN = keccak256("eip4337.bls.domain");
+
+ //copied from BLS.sol
+ uint256 public constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
+
+ address public immutable entryPoint;
+
+ constructor(address _entryPoint) {
+ entryPoint = _entryPoint;
+ }
+
+ /**
+ * return the public key of this account.
+ * @param userOp the UserOperation that we need the account's public key for.
+ * @return publicKey - the public key from a BLS keypair the Aggregator will use to verify this UserOp;
+ * normally public key will be queried from the deployed BLSAccount itself;
+ * the public key will be read from the 'initCode' if the account is not deployed yet;
+ */
+ function getUserOpPublicKey(PackedUserOperation memory userOp) public view returns (uint256[4] memory publicKey) {
+ bytes memory initCode = userOp.initCode;
+ if (initCode.length > 0) {
+ publicKey = getTrailingPublicKey(initCode);
+ } else {
+ return IBLSAccount(userOp.sender).getBlsPublicKey{gas : 50000}();
+ }
+ }
+
+ /**
+ * return the trailing 4 words of input data
+ */
+ function getTrailingPublicKey(bytes memory data) public pure returns (uint256[4] memory publicKey) {
+ uint256 len = data.length;
+ require(len > 32 * 4, "data too short for sig");
+
+ /* solhint-disable-next-line no-inline-assembly */
+ assembly {
+ // actual buffer starts at data+32, so last 128 bytes start at data+32+len-128 = data+len-96
+ let ofs := sub(add(data, len), 96)
+ mstore(publicKey, mload(ofs))
+ mstore(add(publicKey, 32), mload(add(ofs, 32)))
+ mstore(add(publicKey, 64), mload(add(ofs, 64)))
+ mstore(add(publicKey, 96), mload(add(ofs, 96)))
+ }
+ }
+
+ /// @inheritdoc IAggregator
+ function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature)
+ external view override {
+ require(signature.length == 64, "BLS: invalid signature");
+ (uint256[2] memory blsSignature) = abi.decode(signature, (uint256[2]));
+
+ uint256 userOpsLen = userOps.length;
+ uint256[4][] memory blsPublicKeys = new uint256[4][](userOpsLen);
+ uint256[2][] memory messages = new uint256[2][](userOpsLen);
+ for (uint256 i = 0; i < userOpsLen; i++) {
+
+ PackedUserOperation memory userOp = userOps[i];
+ blsPublicKeys[i] = getUserOpPublicKey(userOp);
+
+ messages[i] = _userOpToMessage(userOp, _getPublicKeyHash(blsPublicKeys[i]));
+ }
+ require(BLSOpen.verifyMultiple(blsSignature, blsPublicKeys, messages), "BLS: validateSignatures failed");
+ }
+
+ /**
+ * get a hash of userOp
+ * NOTE: this hash is not the same as UserOperation.hash()
+ * (slightly less efficient, since it uses memory userOp)
+ */
+ function internalUserOpHash(PackedUserOperation memory userOp) internal pure returns (bytes32) {
+ return keccak256(abi.encode(
+ userOp.sender,
+ userOp.nonce,
+ keccak256(userOp.initCode),
+ keccak256(userOp.callData),
+ userOp.accountGasLimits,
+ userOp.preVerificationGas,
+ userOp.gasFees,
+ keccak256(userOp.paymasterAndData)
+ ));
+ }
+
+ /**
+ * return the BLS "message" for the given UserOp.
+ * the account checks the signature over this value using its public key
+ */
+ function userOpToMessage(PackedUserOperation memory userOp) public view returns (uint256[2] memory) {
+ bytes32 publicKeyHash = _getPublicKeyHash(getUserOpPublicKey(userOp));
+ return _userOpToMessage(userOp, publicKeyHash);
+ }
+
+ function _userOpToMessage(PackedUserOperation memory userOp, bytes32 publicKeyHash) internal view returns (uint256[2] memory) {
+ bytes32 userOpHash = _getUserOpHash(userOp, publicKeyHash);
+ return BLSOpen.hashToPoint(BLS_DOMAIN, abi.encodePacked(userOpHash));
+ }
+
+
+ function getUserOpHash(PackedUserOperation memory userOp) public view returns (bytes32) {
+ bytes32 publicKeyHash = _getPublicKeyHash(getUserOpPublicKey(userOp));
+ return _getUserOpHash(userOp, publicKeyHash);
+ }
+
+ function _getUserOpHash(PackedUserOperation memory userOp, bytes32 publicKeyHash) internal view returns (bytes32) {
+ return keccak256(abi.encode(internalUserOpHash(userOp), publicKeyHash, address(this), block.chainid, entryPoint));
+ }
+
+ function _getPublicKeyHash(uint256[4] memory publicKey) internal pure returns(bytes32) {
+ return keccak256(abi.encode(publicKey));
+ }
+ /**
+ * validate signature of a single userOp
+ * This method is called after EntryPoint.simulateValidation() returns an aggregator.
+ * First it validates the signature over the userOp. then it return data to be used when creating the handleOps:
+ * @param userOp the userOperation received from the user.
+ * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.
+ * (usually empty, unless account and aggregator support some kind of "multisig"
+ */
+ function validateUserOpSignature(PackedUserOperation calldata userOp)
+ external view returns (bytes memory sigForUserOp) {
+ uint256[2] memory signature = abi.decode(userOp.signature, (uint256[2]));
+ uint256[4] memory pubkey = getUserOpPublicKey(userOp);
+ uint256[2] memory message = _userOpToMessage(userOp, _getPublicKeyHash(pubkey));
+
+ require(BLSOpen.verifySingle(signature, pubkey, message), "BLS: wrong sig");
+ return "";
+ }
+
+
+ /**
+ * aggregate multiple signatures into a single value.
+ * This method is called off-chain to calculate the signature to pass with handleOps()
+ * bundler MAY use optimized custom code perform this aggregation
+ * @param userOps array of UserOperations to collect the signatures from.
+ * @return aggregatedSignature the aggregated signature
+ */
+ function aggregateSignatures(PackedUserOperation[] calldata userOps) external pure returns (bytes memory aggregatedSignature) {
+ BLSHelper.XY[] memory points = new BLSHelper.XY[](userOps.length);
+ for (uint256 i = 0; i < points.length; i++) {
+ (uint256 x, uint256 y) = abi.decode(userOps[i].signature, (uint256, uint256));
+ points[i] = BLSHelper.XY(x, y);
+ }
+ BLSHelper.XY memory sum = BLSHelper.sum(points, N);
+ return abi.encode(sum.x, sum.y);
+ }
+
+ /**
+ * allow staking for this aggregator
+ * there is no limit on stake or delay, but it is not a problem, since it is a permissionless
+ * signature aggregator, which doesn't support unstaking.
+ * @param unstakeDelaySec - the required unstaked delay
+ */
+ function addStake(uint32 unstakeDelaySec) external payable {
+ IEntryPoint(entryPoint).addStake{value : msg.value}(unstakeDelaySec);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/IBLSAccount.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/IBLSAccount.sol
new file mode 100644
index 000000000..c7d0e7f6c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/IBLSAccount.sol
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-3.0-only
+pragma solidity >=0.7.5;
+
+import "../../interfaces/IAccount.sol";
+
+/**
+ * a BLS account should expose its own public key.
+ */
+interface IBLSAccount is IAccount {
+ event PublicKeyChanged(uint256[4] oldPublicKey, uint256[4] newPublicKey);
+
+ /**
+ * @return public key from a BLS keypair that is used to verify the BLS signature, both separately and aggregated.
+ */
+ function getBlsPublicKey() external view returns (uint256[4] memory);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/BLSOpen.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/BLSOpen.sol
new file mode 100644
index 000000000..914955b3d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/BLSOpen.sol
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.23;
+
+import { BLS } from "./hubble-contracts/contracts/libs/BLS.sol";
+
+library BLSOpen {
+ function verifySingle(
+ uint256[2] memory signature,
+ uint256[4] memory pubkey,
+ uint256[2] memory message
+ ) external view returns (bool) {
+ uint256[4][] memory pubkeys = new uint256[4][](1);
+ uint256[2][] memory messages = new uint256[2][](1);
+ pubkeys[0] = pubkey;
+ messages[0] = message;
+
+ (bool verified, bool callSuccess) = BLS.verifyMultiple(
+ signature,
+ pubkeys,
+ messages
+ );
+ return callSuccess && verified;
+
+ // // NB: (result, success) opposite of `call` convention (success, result).
+ // (bool verified, bool callSuccess) = BLS.verifySingle(
+ // signature,
+ // pubkey,
+ // message
+ // );
+ // return callSuccess && verified;
+ }
+
+ function verifyMultiple(
+ uint256[2] memory signature,
+ uint256[4][] memory pubkeys,
+ uint256[2][] memory messages
+ ) external view returns (bool) {
+ (bool verified, bool callSuccess) = BLS.verifyMultiple(
+ signature,
+ pubkeys,
+ messages
+ );
+ return callSuccess && verified;
+ }
+
+ function hashToPoint(
+ bytes32 domain,
+ bytes memory message
+ ) external view returns (uint256[2] memory) {
+ return BLS.hashToPoint(
+ domain,
+ message
+ );
+ }
+
+ function isZeroBLSKey(uint256[4] memory blsKey) public pure returns (bool) {
+ bool isZero = true;
+ for (uint256 i=0; isZero && i<4; i++) {
+ isZero = (blsKey[i] == 0);
+ }
+ return isZero;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/hubble-contracts/contracts/libs/BLS.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/hubble-contracts/contracts/libs/BLS.sol
new file mode 100644
index 000000000..e02bc10c3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/hubble-contracts/contracts/libs/BLS.sol
@@ -0,0 +1,440 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >= 0.6.12;
+
+import { ModexpInverse, ModexpSqrt } from "./ModExp.sol";
+import {
+ BNPairingPrecompileCostEstimator
+} from "./BNPairingPrecompileCostEstimator.sol";
+
+/**
+ @title Boneh–Lynn–Shacham (BLS) signature scheme on Barreto-Naehrig 254 bit curve (BN-254)
+ @notice We use BLS signature aggregation to reduce the size of signature data to store on chain.
+ @dev We use G1 points for signatures and messages, and G2 points for public keys
+ */
+library BLS {
+ // Field order
+ // prettier-ignore
+ uint256 private constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
+
+ // Negated genarator of G2
+ // prettier-ignore
+ uint256 private constant N_G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
+ // prettier-ignore
+ uint256 private constant N_G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
+ // prettier-ignore
+ uint256 private constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052;
+ // prettier-ignore
+ uint256 private constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653;
+
+ // sqrt(-3)
+ // prettier-ignore
+ uint256 private constant Z0 = 0x0000000000000000b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd;
+ // (sqrt(-3) - 1) / 2
+ // prettier-ignore
+ uint256 private constant Z1 = 0x000000000000000059e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe;
+
+ // prettier-ignore
+ uint256 private constant T24 = 0x1000000000000000000000000000000000000000000000000;
+ // prettier-ignore
+ uint256 private constant MASK24 = 0xffffffffffffffffffffffffffffffffffffffffffffffff;
+
+ // estimator address
+// address private constant COST_ESTIMATOR_ADDRESS = new 0x22E4a5251C1F02de8369Dd6f192033F6CB7531A4;
+
+ function verifySingle(
+ uint256[2] memory signature,
+ uint256[4] memory pubkey,
+ uint256[2] memory message
+ ) internal view returns (bool, bool) {
+ uint256[12] memory input =
+ [
+ signature[0],
+ signature[1],
+ N_G2_X1,
+ N_G2_X0,
+ N_G2_Y1,
+ N_G2_Y0,
+ message[0],
+ message[1],
+ pubkey[1],
+ pubkey[0],
+ pubkey[3],
+ pubkey[2]
+ ];
+ uint256[1] memory out;
+ uint256 precompileGasCost = gasleft();
+// BNPairingPrecompileCostEstimator(COST_ESTIMATOR_ADDRESS).getGasCost(
+// 2
+// );
+ bool callSuccess;
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ callSuccess := staticcall(
+ precompileGasCost,
+ 8,
+ input,
+ 384,
+ out,
+ 0x20
+ )
+ }
+ if (!callSuccess) {
+ return (false, false);
+ }
+ return (out[0] != 0, true);
+ }
+
+ function verifyMultiple(
+ uint256[2] memory signature,
+ uint256[4][] memory pubkeys,
+ uint256[2][] memory messages
+ ) internal view returns (bool checkResult, bool callSuccess) {
+ uint256 size = pubkeys.length;
+ require(size > 0, "BLS: number of public key is zero");
+ require(
+ size == messages.length,
+ "BLS: number of public keys and messages must be equal"
+ );
+ uint256 inputSize = (size + 1) * 6;
+ uint256[] memory input = new uint256[](inputSize);
+ input[0] = signature[0];
+ input[1] = signature[1];
+ input[2] = N_G2_X1;
+ input[3] = N_G2_X0;
+ input[4] = N_G2_Y1;
+ input[5] = N_G2_Y0;
+ for (uint256 i = 0; i < size; i++) {
+ input[i * 6 + 6] = messages[i][0];
+ input[i * 6 + 7] = messages[i][1];
+ input[i * 6 + 8] = pubkeys[i][1];
+ input[i * 6 + 9] = pubkeys[i][0];
+ input[i * 6 + 10] = pubkeys[i][3];
+ input[i * 6 + 11] = pubkeys[i][2];
+ }
+ uint256[1] memory out;
+
+ // prettier-ignore
+ uint256 precompileGasCost = gasleft();
+// uint256 precompileGasCost = BNPairingPrecompileCostEstimator(COST_ESTIMATOR_ADDRESS).getGasCost(size + 1);
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ callSuccess := staticcall(
+ precompileGasCost,
+ 8,
+ add(input, 0x20),
+ mul(inputSize, 0x20),
+ out,
+ 0x20
+ )
+ }
+ if (!callSuccess) {
+ return (false, false);
+ }
+ return (out[0] != 0, true);
+ }
+
+ /**
+ @notice Fouque-Tibouchi Hash to Curve
+ */
+ function hashToPoint(bytes32 domain, bytes memory message)
+ internal
+ view
+ returns (uint256[2] memory)
+ {
+ uint256[2] memory u = hashToField(domain, message);
+ uint256[2] memory p0 = mapToPoint(u[0]);
+ uint256[2] memory p1 = mapToPoint(u[1]);
+ uint256[4] memory bnAddInput;
+ bnAddInput[0] = p0[0];
+ bnAddInput[1] = p0[1];
+ bnAddInput[2] = p1[0];
+ bnAddInput[3] = p1[1];
+ bool success;
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ success := staticcall(sub(gas(), 2000), 6, bnAddInput, 128, p0, 64)
+ switch success
+ case 0 {
+ invalid()
+ }
+ }
+ require(success, "BLS: bn add call failed");
+ return p0;
+ }
+
+ function mapToPoint(uint256 _x)
+ internal
+ pure
+ returns (uint256[2] memory p)
+ {
+ require(_x < N, "mapToPointFT: invalid field element");
+ uint256 x = _x;
+
+ (, bool decision) = sqrt(x);
+
+ uint256 a0 = mulmod(x, x, N);
+ a0 = addmod(a0, 4, N);
+ uint256 a1 = mulmod(x, Z0, N);
+ uint256 a2 = mulmod(a1, a0, N);
+ a2 = inverse(a2);
+ a1 = mulmod(a1, a1, N);
+ a1 = mulmod(a1, a2, N);
+
+ // x1
+ a1 = mulmod(x, a1, N);
+ x = addmod(Z1, N - a1, N);
+ // check curve
+ a1 = mulmod(x, x, N);
+ a1 = mulmod(a1, x, N);
+ a1 = addmod(a1, 3, N);
+ bool found;
+ (a1, found) = sqrt(a1);
+ if (found) {
+ if (!decision) {
+ a1 = N - a1;
+ }
+ return [x, a1];
+ }
+
+ // x2
+ x = N - addmod(x, 1, N);
+ // check curve
+ a1 = mulmod(x, x, N);
+ a1 = mulmod(a1, x, N);
+ a1 = addmod(a1, 3, N);
+ (a1, found) = sqrt(a1);
+ if (found) {
+ if (!decision) {
+ a1 = N - a1;
+ }
+ return [x, a1];
+ }
+
+ // x3
+ x = mulmod(a0, a0, N);
+ x = mulmod(x, x, N);
+ x = mulmod(x, a2, N);
+ x = mulmod(x, a2, N);
+ x = addmod(x, 1, N);
+ // must be on curve
+ a1 = mulmod(x, x, N);
+ a1 = mulmod(a1, x, N);
+ a1 = addmod(a1, 3, N);
+ (a1, found) = sqrt(a1);
+ require(found, "BLS: bad ft mapping implementation");
+ if (!decision) {
+ a1 = N - a1;
+ }
+ return [x, a1];
+ }
+
+ function isValidSignature(uint256[2] memory signature)
+ internal
+ pure
+ returns (bool)
+ {
+ if ((signature[0] >= N) || (signature[1] >= N)) {
+ return false;
+ } else {
+ return isOnCurveG1(signature);
+ }
+ }
+
+ function isOnCurveG1(uint256[2] memory point)
+ internal
+ pure
+ returns (bool _isOnCurve)
+ {
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let t0 := mload(point)
+ let t1 := mload(add(point, 32))
+ let t2 := mulmod(t0, t0, N)
+ t2 := mulmod(t2, t0, N)
+ t2 := addmod(t2, 3, N)
+ t1 := mulmod(t1, t1, N)
+ _isOnCurve := eq(t1, t2)
+ }
+ }
+
+ function isOnCurveG2(uint256[4] memory point)
+ internal
+ pure
+ returns (bool _isOnCurve)
+ {
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ // x0, x1
+ let t0 := mload(point)
+ let t1 := mload(add(point, 32))
+ // x0 ^ 2
+ let t2 := mulmod(t0, t0, N)
+ // x1 ^ 2
+ let t3 := mulmod(t1, t1, N)
+ // 3 * x0 ^ 2
+ let t4 := add(add(t2, t2), t2)
+ // 3 * x1 ^ 2
+ let t5 := addmod(add(t3, t3), t3, N)
+ // x0 * (x0 ^ 2 - 3 * x1 ^ 2)
+ t2 := mulmod(add(t2, sub(N, t5)), t0, N)
+ // x1 * (3 * x0 ^ 2 - x1 ^ 2)
+ t3 := mulmod(add(t4, sub(N, t3)), t1, N)
+
+ // x ^ 3 + b
+ t0 := addmod(
+ t2,
+ 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5,
+ N
+ )
+ t1 := addmod(
+ t3,
+ 0x009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2,
+ N
+ )
+
+ // y0, y1
+ t2 := mload(add(point, 64))
+ t3 := mload(add(point, 96))
+ // y ^ 2
+ t4 := mulmod(addmod(t2, t3, N), addmod(t2, sub(N, t3), N), N)
+ t3 := mulmod(shl(1, t2), t3, N)
+
+ // y ^ 2 == x ^ 3 + b
+ _isOnCurve := and(eq(t0, t4), eq(t1, t3))
+ }
+ }
+
+ function sqrt(uint256 xx) internal pure returns (uint256 x, bool hasRoot) {
+ x = ModexpSqrt.run(xx);
+ hasRoot = mulmod(x, x, N) == xx;
+ }
+
+ function inverse(uint256 a) internal pure returns (uint256) {
+ return ModexpInverse.run(a);
+ }
+
+ function hashToField(bytes32 domain, bytes memory messages)
+ internal
+ pure
+ returns (uint256[2] memory)
+ {
+ bytes memory _msg = expandMsgTo96(domain, messages);
+ uint256 u0;
+ uint256 u1;
+ uint256 a0;
+ uint256 a1;
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let p := add(_msg, 24)
+ u1 := and(mload(p), MASK24)
+ p := add(_msg, 48)
+ u0 := and(mload(p), MASK24)
+ a0 := addmod(mulmod(u1, T24, N), u0, N)
+ p := add(_msg, 72)
+ u1 := and(mload(p), MASK24)
+ p := add(_msg, 96)
+ u0 := and(mload(p), MASK24)
+ a1 := addmod(mulmod(u1, T24, N), u0, N)
+ }
+ return [a0, a1];
+ }
+
+ function expandMsgTo96(bytes32 domain, bytes memory message)
+ internal
+ pure
+ returns (bytes memory)
+ {
+ // zero<64>|msg|lib_str<2>|I2OSP(0, 1)<1>|dst|dst_len<1>
+ uint256 t0 = message.length;
+ bytes memory msg0 = new bytes(32 + t0 + 64 + 4);
+ bytes memory out = new bytes(96);
+ // b0
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let p := add(msg0, 96)
+ for {
+ let z := 0
+ } lt(z, t0) {
+ z := add(z, 32)
+ } {
+ mstore(add(p, z), mload(add(message, add(z, 32))))
+ }
+ p := add(p, t0)
+
+ mstore8(p, 0)
+ p := add(p, 1)
+ mstore8(p, 96)
+ p := add(p, 1)
+ mstore8(p, 0)
+ p := add(p, 1)
+
+ mstore(p, domain)
+ p := add(p, 32)
+ mstore8(p, 32)
+ }
+ bytes32 b0 = sha256(msg0);
+ bytes32 bi;
+ t0 = 32 + 34;
+
+ // resize intermediate message
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ mstore(msg0, t0)
+ }
+
+ // b1
+
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ mstore(add(msg0, 32), b0)
+ mstore8(add(msg0, 64), 1)
+ mstore(add(msg0, 65), domain)
+ mstore8(add(msg0, add(32, 65)), 32)
+ }
+
+ bi = sha256(msg0);
+
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ mstore(add(out, 32), bi)
+ }
+
+ // b2
+
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let t := xor(b0, bi)
+ mstore(add(msg0, 32), t)
+ mstore8(add(msg0, 64), 2)
+ mstore(add(msg0, 65), domain)
+ mstore8(add(msg0, add(32, 65)), 32)
+ }
+
+ bi = sha256(msg0);
+
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ mstore(add(out, 64), bi)
+ }
+
+ // b3
+
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let t := xor(b0, bi)
+ mstore(add(msg0, 32), t)
+ mstore8(add(msg0, 64), 3)
+ mstore(add(msg0, 65), domain)
+ mstore8(add(msg0, add(32, 65)), 32)
+ }
+
+ bi = sha256(msg0);
+
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ mstore(add(out, 96), bi)
+ }
+
+ return out;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/hubble-contracts/contracts/libs/ModExp.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/hubble-contracts/contracts/libs/ModExp.sol
new file mode 100644
index 000000000..6fd08f118
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/bls/lib/hubble-contracts/contracts/libs/ModExp.sol
@@ -0,0 +1,652 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >= 0.6.12;
+
+/**
+ @title Compute Inverse by Modular Exponentiation
+ @notice Compute $input^(N - 2) mod N$ using Addition Chain method.
+ Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
+ and N - 2 = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45
+ @dev the function body is generated with the modified addchain script
+ see https://github.com/kobigurk/addchain/commit/2c37a2ace567a9bdc680b4e929c94aaaa3ec700f
+ */
+library ModexpInverse {
+ function run(uint256 t2) internal pure returns (uint256 t0) {
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let
+ n
+ := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
+ t0 := mulmod(t2, t2, n)
+ let t5 := mulmod(t0, t2, n)
+ let t1 := mulmod(t5, t0, n)
+ let t3 := mulmod(t5, t5, n)
+ let t8 := mulmod(t1, t0, n)
+ let t4 := mulmod(t3, t5, n)
+ let t6 := mulmod(t3, t1, n)
+ t0 := mulmod(t3, t3, n)
+ let t7 := mulmod(t8, t3, n)
+ t3 := mulmod(t4, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t7, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t7, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t7, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ }
+ }
+}
+
+/**
+ @title Compute Squre Root by Modular Exponentiation
+ @notice Compute $input^{(N + 1) / 4} mod N$ using Addition Chain method.
+ Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
+ and (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52
+ */
+library ModexpSqrt {
+ function run(uint256 t6) internal pure returns (uint256 t0) {
+ // solium-disable-next-line security/no-inline-assembly
+ assembly {
+ let
+ n
+ := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
+
+ t0 := mulmod(t6, t6, n)
+ let t4 := mulmod(t0, t6, n)
+ let t2 := mulmod(t4, t0, n)
+ let t3 := mulmod(t4, t4, n)
+ let t8 := mulmod(t2, t0, n)
+ let t1 := mulmod(t3, t4, n)
+ let t5 := mulmod(t3, t2, n)
+ t0 := mulmod(t3, t3, n)
+ let t7 := mulmod(t8, t3, n)
+ t3 := mulmod(t1, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t7, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t7, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t8, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t7, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t6, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t5, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t4, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t3, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t2, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t0, n)
+ t0 := mulmod(t0, t1, n)
+ t0 := mulmod(t0, t0, n)
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/callback/TokenCallbackHandler.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/callback/TokenCallbackHandler.sol
new file mode 100644
index 000000000..2b4a72ffc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/callback/TokenCallbackHandler.sol
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable no-empty-blocks */
+
+import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
+import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
+import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
+
+/**
+ * Token callback handler.
+ * Handles supported tokens' callbacks, allowing account receiving these tokens.
+ */
+abstract contract TokenCallbackHandler is IERC721Receiver, IERC1155Receiver {
+
+ function onERC721Received(
+ address,
+ address,
+ uint256,
+ bytes calldata
+ ) external pure override returns (bytes4) {
+ return IERC721Receiver.onERC721Received.selector;
+ }
+
+ function onERC1155Received(
+ address,
+ address,
+ uint256,
+ uint256,
+ bytes calldata
+ ) external pure override returns (bytes4) {
+ return IERC1155Receiver.onERC1155Received.selector;
+ }
+
+ function onERC1155BatchReceived(
+ address,
+ address,
+ uint256[] calldata,
+ uint256[] calldata,
+ bytes calldata
+ ) external pure override returns (bytes4) {
+ return IERC1155Receiver.onERC1155BatchReceived.selector;
+ }
+
+ function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
+ return
+ interfaceId == type(IERC721Receiver).interfaceId ||
+ interfaceId == type(IERC1155Receiver).interfaceId ||
+ interfaceId == type(IERC165).interfaceId;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/IOracle.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/IOracle.sol
new file mode 100644
index 000000000..a8c238126
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/IOracle.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.23;
+
+interface IOracle {
+ function decimals() external view returns (uint8);
+ function latestRoundData()
+ external
+ view
+ returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/OracleHelper.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/OracleHelper.sol
new file mode 100644
index 000000000..49e6fcf5c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/OracleHelper.sol
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable not-rely-on-time */
+
+import "./IOracle.sol";
+
+/// @title Helper functions for dealing with various forms of price feed oracles.
+/// @notice Maintains a price cache and updates the current price if needed.
+/// In the best case scenario we have a direct oracle from the token to the native asset.
+/// Also support tokens that have no direct price oracle to the native asset.
+/// Sometimes oracles provide the price in the opposite direction of what we need in the moment.
+abstract contract OracleHelper {
+
+ event TokenPriceUpdated(uint256 currentPrice, uint256 previousPrice, uint256 cachedPriceTimestamp);
+
+ uint256 private constant PRICE_DENOMINATOR = 1e26;
+
+ struct OracleHelperConfig {
+
+ /// @notice The price cache will be returned without even fetching the oracles for this number of seconds
+ uint48 cacheTimeToLive;
+
+ /// @notice The maximum acceptable age of the price oracle round
+ uint48 maxOracleRoundAge;
+
+ /// @notice The Oracle contract used to fetch the latest token prices
+ IOracle tokenOracle;
+
+ /// @notice The Oracle contract used to fetch the latest native asset prices. Only needed if tokenToNativeOracle flag is not set.
+ IOracle nativeOracle;
+
+ /// @notice If 'true' we will fetch price directly from tokenOracle
+ /// @notice If 'false' we will use nativeOracle to establish a token price through a shared third currency
+ bool tokenToNativeOracle;
+
+ /// @notice 'false' if price is bridging-asset-per-token (or native-asset-per-token), 'true' if price is tokens-per-bridging-asset
+ bool tokenOracleReverse;
+
+ /// @notice 'false' if price is bridging-asset-per-native-asset, 'true' if price is native-asset-per-bridging-asset
+ bool nativeOracleReverse;
+
+ /// @notice The price update threshold percentage from PRICE_DENOMINATOR that triggers a price update (1e26 = 100%)
+ uint256 priceUpdateThreshold;
+
+ }
+
+ /// @notice The cached token price from the Oracle, always in (native-asset-per-token) * PRICE_DENOMINATOR format
+ uint256 public cachedPrice;
+
+ /// @notice The timestamp of a block when the cached price was updated
+ uint48 public cachedPriceTimestamp;
+
+ OracleHelperConfig private oracleHelperConfig;
+
+ /// @notice The "10^(tokenOracle.decimals)" value used for the price calculation
+ uint128 private tokenOracleDecimalPower;
+
+ /// @notice The "10^(nativeOracle.decimals)" value used for the price calculation
+ uint128 private nativeOracleDecimalPower;
+
+ constructor (
+ OracleHelperConfig memory _oracleHelperConfig
+ ) {
+ cachedPrice = type(uint256).max; // initialize the storage slot to invalid value
+ _setOracleConfiguration(
+ _oracleHelperConfig
+ );
+ }
+
+ function _setOracleConfiguration(
+ OracleHelperConfig memory _oracleHelperConfig
+ ) private {
+ oracleHelperConfig = _oracleHelperConfig;
+ require(_oracleHelperConfig.priceUpdateThreshold <= PRICE_DENOMINATOR, "TPM: update threshold too high");
+ tokenOracleDecimalPower = uint128(10 ** oracleHelperConfig.tokenOracle.decimals());
+ if (oracleHelperConfig.tokenToNativeOracle) {
+ require(address(oracleHelperConfig.nativeOracle) == address(0), "TPM: native oracle must be zero");
+ nativeOracleDecimalPower = 1;
+ } else {
+ nativeOracleDecimalPower = uint128(10 ** oracleHelperConfig.nativeOracle.decimals());
+ }
+ }
+
+ /// @notice Updates the token price by fetching the latest price from the Oracle.
+ /// @param force true to force cache update, even if called after short time or the change is lower than the update threshold.
+ /// @return newPrice the new cached token price
+ function updateCachedPrice(bool force) public returns (uint256) {
+ uint256 cacheTimeToLive = oracleHelperConfig.cacheTimeToLive;
+ uint256 cacheAge = block.timestamp - cachedPriceTimestamp;
+ if (!force && cacheAge <= cacheTimeToLive) {
+ return cachedPrice;
+ }
+ uint256 priceUpdateThreshold = oracleHelperConfig.priceUpdateThreshold;
+ IOracle tokenOracle = oracleHelperConfig.tokenOracle;
+ IOracle nativeOracle = oracleHelperConfig.nativeOracle;
+
+ uint256 _cachedPrice = cachedPrice;
+ uint256 tokenPrice = fetchPrice(tokenOracle);
+ uint256 nativeAssetPrice = 1;
+ // If the 'TokenOracle' returns the price in the native asset units there is no need to fetch native asset price
+ if (!oracleHelperConfig.tokenToNativeOracle) {
+ nativeAssetPrice = fetchPrice(nativeOracle);
+ }
+ uint256 newPrice = calculatePrice(
+ tokenPrice,
+ nativeAssetPrice,
+ oracleHelperConfig.tokenOracleReverse,
+ oracleHelperConfig.nativeOracleReverse
+ );
+ uint256 priceRatio = PRICE_DENOMINATOR * newPrice / _cachedPrice;
+ bool updateRequired = force ||
+ priceRatio > PRICE_DENOMINATOR + priceUpdateThreshold ||
+ priceRatio < PRICE_DENOMINATOR - priceUpdateThreshold;
+ if (!updateRequired) {
+ return _cachedPrice;
+ }
+ cachedPrice = newPrice;
+ cachedPriceTimestamp = uint48(block.timestamp);
+ emit TokenPriceUpdated(newPrice, _cachedPrice, cachedPriceTimestamp);
+ return newPrice;
+ }
+
+ /**
+ * Calculate the effective price of the selected token denominated in native asset.
+ *
+ * @param tokenPrice - the price of the token relative to a native asset or a bridging asset like the U.S. dollar.
+ * @param nativeAssetPrice - the price of the native asset relative to a bridging asset or 1 if no bridging needed.
+ * @param tokenOracleReverse - flag indicating direction of the "tokenPrice".
+ * @param nativeOracleReverse - flag indicating direction of the "nativeAssetPrice".
+ * @return the native-asset-per-token price multiplied by the PRICE_DENOMINATOR constant.
+ */
+ function calculatePrice(
+ uint256 tokenPrice,
+ uint256 nativeAssetPrice,
+ bool tokenOracleReverse,
+ bool nativeOracleReverse
+ ) private view returns (uint256){
+ // tokenPrice is normalized as bridging-asset-per-token
+ if (tokenOracleReverse) {
+ // inverting tokenPrice that was tokens-per-bridging-asset (or tokens-per-native-asset)
+ tokenPrice = PRICE_DENOMINATOR * tokenOracleDecimalPower / tokenPrice;
+ } else {
+ // tokenPrice already bridging-asset-per-token (or native-asset-per-token)
+ tokenPrice = PRICE_DENOMINATOR * tokenPrice / tokenOracleDecimalPower;
+ }
+
+ if (nativeOracleReverse) {
+ // multiplying by nativeAssetPrice that is native-asset-per-bridging-asset
+ // => result = (bridging-asset / token) * (native-asset / bridging-asset) = native-asset / token
+ return nativeAssetPrice * tokenPrice / nativeOracleDecimalPower;
+ } else {
+ // dividing by nativeAssetPrice that is bridging-asset-per-native-asset
+ // => result = (bridging-asset / token) / (bridging-asset / native-asset) = native-asset / token
+ return tokenPrice * nativeOracleDecimalPower / nativeAssetPrice;
+ }
+ }
+
+ /// @notice Fetches the latest price from the given Oracle.
+ /// @dev This function is used to get the latest price from the tokenOracle or nativeOracle.
+ /// @param _oracle The Oracle contract to fetch the price from.
+ /// @return price The latest price fetched from the Oracle.
+ function fetchPrice(IOracle _oracle) internal view returns (uint256 price) {
+ (uint80 roundId, int256 answer,, uint256 updatedAt, uint80 answeredInRound) = _oracle.latestRoundData();
+ require(answer > 0, "TPM: Chainlink price <= 0");
+ require(updatedAt >= block.timestamp - oracleHelperConfig.maxOracleRoundAge, "TPM: Incomplete round");
+ require(answeredInRound >= roundId, "TPM: Stale price");
+ price = uint256(answer);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/UniswapHelper.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/UniswapHelper.sol
new file mode 100644
index 000000000..a670ced8d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/samples/utils/UniswapHelper.sol
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.23;
+
+/* solhint-disable not-rely-on-time */
+
+import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+
+import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
+import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol";
+
+abstract contract UniswapHelper {
+ event UniswapReverted(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMin);
+
+ uint256 private constant PRICE_DENOMINATOR = 1e26;
+
+ struct UniswapHelperConfig {
+ /// @notice Minimum native asset amount to receive from a single swap
+ uint256 minSwapAmount;
+
+ uint24 uniswapPoolFee;
+
+ uint8 slippage;
+ }
+
+ /// @notice The Uniswap V3 SwapRouter contract
+ ISwapRouter public immutable uniswap;
+
+ /// @notice The ERC20 token used for transaction fee payments
+ IERC20 public immutable token;
+
+ /// @notice The ERC-20 token that wraps the native asset for current chain
+ IERC20 public immutable wrappedNative;
+
+ UniswapHelperConfig private uniswapHelperConfig;
+
+ constructor(
+ IERC20 _token,
+ IERC20 _wrappedNative,
+ ISwapRouter _uniswap,
+ UniswapHelperConfig memory _uniswapHelperConfig
+ ){
+ _token.approve(address(_uniswap), type(uint256).max);
+ token = _token;
+ wrappedNative = _wrappedNative;
+ uniswap = _uniswap;
+ _setUniswapHelperConfiguration(_uniswapHelperConfig);
+ }
+
+ function _setUniswapHelperConfiguration(UniswapHelperConfig memory _uniswapHelperConfig) internal {
+ uniswapHelperConfig = _uniswapHelperConfig;
+ }
+
+ function _maybeSwapTokenToWeth(IERC20 tokenIn, uint256 quote) internal returns (uint256) {
+ uint256 tokenBalance = tokenIn.balanceOf(address(this));
+ uint256 amountOutMin = addSlippage(tokenToWei(tokenBalance, quote), uniswapHelperConfig.slippage);
+ if (amountOutMin < uniswapHelperConfig.minSwapAmount) {
+ return 0;
+ }
+ // note: calling 'swapToToken' but destination token is Wrapped Ether
+ return swapToToken(
+ address(tokenIn),
+ address(wrappedNative),
+ tokenBalance,
+ amountOutMin,
+ uniswapHelperConfig.uniswapPoolFee
+ );
+ }
+
+ function addSlippage(uint256 amount, uint8 slippage) private pure returns (uint256) {
+ return amount * (1000 - slippage) / 1000;
+ }
+
+
+ function tokenToWei(uint256 amount, uint256 price) public pure returns (uint256) {
+ return amount * price / PRICE_DENOMINATOR;
+ }
+
+ function weiToToken(uint256 amount, uint256 price) public pure returns (uint256) {
+ return amount * PRICE_DENOMINATOR / price;
+ }
+
+ function unwrapWeth(uint256 amount) internal {
+ IPeripheryPayments(address(uniswap)).unwrapWETH9(amount, address(this));
+ }
+
+ // swap ERC-20 tokens at market price
+ function swapToToken(
+ address tokenIn,
+ address tokenOut,
+ uint256 amountIn,
+ uint256 amountOutMin,
+ uint24 fee
+ ) internal returns (uint256 amountOut) {
+ ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams(
+ tokenIn, //tokenIn
+ tokenOut, //tokenOut
+ fee,
+ address(uniswap),
+ block.timestamp, //deadline
+ amountIn,
+ amountOutMin,
+ 0
+ );
+ try uniswap.exactInputSingle(params) returns (uint256 _amountOut) {
+ amountOut = _amountOut;
+ } catch {
+ emit UniswapReverted(tokenIn, tokenOut, amountIn, amountOutMin);
+ amountOut = 0;
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/utils/Exec.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/utils/Exec.sol
new file mode 100644
index 000000000..ee8d71ac0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/contracts/utils/Exec.sol
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: LGPL-3.0-only
+pragma solidity ^0.8.23;
+
+// solhint-disable no-inline-assembly
+
+/**
+ * Utility functions helpful when making different kinds of contract calls in Solidity.
+ */
+library Exec {
+
+ function call(
+ address to,
+ uint256 value,
+ bytes memory data,
+ uint256 txGas
+ ) internal returns (bool success) {
+ assembly ("memory-safe") {
+ success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
+ }
+ }
+
+ function staticcall(
+ address to,
+ bytes memory data,
+ uint256 txGas
+ ) internal view returns (bool success) {
+ assembly ("memory-safe") {
+ success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)
+ }
+ }
+
+ function delegateCall(
+ address to,
+ bytes memory data,
+ uint256 txGas
+ ) internal returns (bool success) {
+ assembly ("memory-safe") {
+ success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
+ }
+ }
+
+ // get returned data from last call or calldelegate
+ function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {
+ assembly ("memory-safe") {
+ let len := returndatasize()
+ if gt(len, maxLen) {
+ len := maxLen
+ }
+ let ptr := mload(0x40)
+ mstore(0x40, add(ptr, add(len, 0x20)))
+ mstore(ptr, len)
+ returndatacopy(add(ptr, 0x20), 0, len)
+ returnData := ptr
+ }
+ }
+
+ // revert with explicit byte array (probably reverted info from call)
+ function revertWithData(bytes memory returnData) internal pure {
+ assembly ("memory-safe") {
+ revert(add(returnData, 32), mload(returnData))
+ }
+ }
+
+ function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {
+ bool success = call(to,0,data,gasleft());
+ if (!success) {
+ revertWithData(getReturnData(maxLen));
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deploy/1_deploy_entrypoint.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deploy/1_deploy_entrypoint.ts
new file mode 100644
index 000000000..fbfdb836b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deploy/1_deploy_entrypoint.ts
@@ -0,0 +1,19 @@
+import { HardhatRuntimeEnvironment } from 'hardhat/types'
+import { DeployFunction } from 'hardhat-deploy/types'
+import { ethers } from 'hardhat'
+
+const deployEntryPoint: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
+ const provider = ethers.provider
+ const from = await provider.getSigner().getAddress()
+
+ const ret = await hre.deployments.deploy('EntryPoint', {
+ from,
+ args: [],
+ gasLimit: 6e6,
+ deterministicDeployment: process.env.SALT ?? true,
+ log: true,
+ })
+ console.log('==entrypoint addr=', ret.address)
+}
+
+export default deployEntryPoint
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deploy/2_deploy_SimpleAccountFactory.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deploy/2_deploy_SimpleAccountFactory.ts
new file mode 100644
index 000000000..88d742915
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deploy/2_deploy_SimpleAccountFactory.ts
@@ -0,0 +1,33 @@
+import { HardhatRuntimeEnvironment } from 'hardhat/types'
+import { DeployFunction } from 'hardhat-deploy/types'
+import { ethers } from 'hardhat'
+
+const deploySimpleAccountFactory: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
+ const provider = ethers.provider
+ const from = await provider.getSigner().getAddress()
+ const network = await provider.getNetwork()
+ // only deploy on local test network.
+
+ const forceDeployFactory = process.argv.join(' ').match(/simple-account-factory/) != null
+
+ if (!forceDeployFactory && network.chainId !== 31337 && network.chainId !== 1337) {
+ return
+ }
+
+ const entrypoint = await hre.deployments.get('EntryPoint')
+ await hre.deployments.deploy('SimpleAccountFactory', {
+ from,
+ args: [entrypoint.address],
+ gasLimit: 6e6,
+ log: true,
+ deterministicDeployment: true,
+ })
+
+ await hre.deployments.deploy('TestCounter', {
+ from,
+ deterministicDeployment: true,
+ log: true,
+ })
+}
+
+export default deploySimpleAccountFactory
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/.chainId
new file mode 100644
index 000000000..7df83ecbe
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/.chainId
@@ -0,0 +1 @@
+42161
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/EntryPoint.json
new file mode 100644
index 000000000..916c23908
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 1,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/arbitrum/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/.chainId
new file mode 100644
index 000000000..105d7d9ad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/.chainId
@@ -0,0 +1 @@
+100
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/EntryPoint.json
new file mode 100644
index 000000000..916c23908
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 1,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/gnosis/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/.chainId
new file mode 100644
index 000000000..7813681f5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/.chainId
@@ -0,0 +1 @@
+5
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/EntryPoint.json
new file mode 100644
index 000000000..916c23908
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 1,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/goerli/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/.chainId
new file mode 100644
index 000000000..f70d7bba4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/.chainId
@@ -0,0 +1 @@
+42
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/EntryPoint.json
new file mode 100644
index 000000000..00ddccecc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/EntryPoint.json
@@ -0,0 +1,1073 @@
+{
+ "address": "0xF63621e54F16eC6e4A732e44EaA7708935f259eF",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "_create2factory",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_perOpOverhead",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint32",
+ "name": "_unstakeDelayBlocks",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "reason",
+ "type": "bytes"
+ }
+ ],
+ "name": "PaymasterPostOpFailed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStake",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelayBlocks",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeAdded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawBlock",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocking",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasPrice",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "addDeposit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ }
+ ],
+ "name": "addDepositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "_unstakeDelayBlocks",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "create2factory",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "paymasters",
+ "type": "address[]"
+ }
+ ],
+ "name": "getPaymastersStake",
+ "outputs": [
+ {
+ "internalType": "uint256[]",
+ "name": "_stakes",
+ "type": "uint256[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "_salt",
+ "type": "uint256"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "getStakeInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint96",
+ "name": "stake",
+ "type": "uint96"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelayBlocks",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint96",
+ "name": "withdrawStake",
+ "type": "uint96"
+ },
+ {
+ "internalType": "uint32",
+ "name": "withdrawBlock",
+ "type": "uint32"
+ }
+ ],
+ "internalType": "struct StakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address payable",
+ "name": "redeemer",
+ "type": "address"
+ }
+ ],
+ "name": "handleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "redeemer",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "enum EntryPoint.PaymentMode",
+ "name": "paymentMode",
+ "type": "uint8"
+ }
+ ],
+ "name": "internalHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "addr",
+ "type": "address"
+ }
+ ],
+ "name": "isContractDeployed",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ }
+ ],
+ "name": "isPaymasterStaked",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "requiredStake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "requiredDelayBlocks",
+ "type": "uint256"
+ }
+ ],
+ "name": "isStaked",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "perOpOverhead",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "gasUsedByPayForSelfOp",
+ "type": "uint256"
+ }
+ ],
+ "name": "simulatePaymasterValidation",
+ "outputs": [
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "gasUsedByPayForOp",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateWalletValidation",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "gasUsedByPayForSelfOp",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "stakes",
+ "outputs": [
+ {
+ "internalType": "uint96",
+ "name": "stake",
+ "type": "uint96"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelayBlocks",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint96",
+ "name": "withdrawStake",
+ "type": "uint96"
+ },
+ {
+ "internalType": "uint32",
+ "name": "withdrawBlock",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unstakeDelayBlocks",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [
+ "0xce0042B868300000d44A59004Da54A005ffdcf9f",
+ 22000,
+ 100
+ ],
+ "solcInputHash": "9255faacf3ae4e81db1326413027bfa0",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_create2factory\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_perOpOverhead\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"_unstakeDelayBlocks\",\"type\":\"uint32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"PaymasterPostOpFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStake\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelayBlocks\",\"type\":\"uint256\"}],\"name\":\"StakeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawBlock\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocking\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasPrice\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"addDeposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"addDepositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_unstakeDelayBlocks\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"create2factory\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"paymasters\",\"type\":\"address[]\"}],\"name\":\"getPaymastersStake\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"_stakes\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_salt\",\"type\":\"uint256\"}],\"name\":\"getSenderAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"getStakeInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelayBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"withdrawStake\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"withdrawBlock\",\"type\":\"uint32\"}],\"internalType\":\"struct StakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"redeemer\",\"type\":\"address\"}],\"name\":\"handleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"redeemer\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"enum EntryPoint.PaymentMode\",\"name\":\"paymentMode\",\"type\":\"uint8\"}],\"name\":\"internalHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isContractDeployed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"}],\"name\":\"isPaymasterStaked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"requiredStake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredDelayBlocks\",\"type\":\"uint256\"}],\"name\":\"isStaked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"perOpOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"gasUsedByPayForSelfOp\",\"type\":\"uint256\"}],\"name\":\"simulatePaymasterValidation\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsedByPayForOp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateWalletValidation\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gasUsedByPayForSelfOp\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"stakes\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelayBlocks\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"withdrawStake\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"withdrawBlock\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unstakeDelayBlocks\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"handleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),address)\":{\"params\":{\"op\":\"the operation to execute\",\"redeemer\":\"the contract to redeem the fee\"}},\"simulatePaymasterValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),uint256)\":{\"params\":{\"gasUsedByPayForSelfOp\":\"- the gas returned by simulateWalletValidation, as these 2 calls should share the same userOp.validationGas quota. The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the paymaster's data\",\"userOp\":\"the user operation to validate.\"}},\"simulateWalletValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes))\":{\"returns\":{\"gasUsedByPayForSelfOp\":\"- gas used by the validation, to pass into simulatePaymasterValidation. The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the wallet's data\"}}},\"version\":1},\"userdoc\":{\"events\":{\"StakeUnlocking(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"}},\"kind\":\"user\",\"methods\":{\"addDeposit()\":{\"notice\":\"add a deposit (just like stake, but with lock=0 cancel any pending unlock\"},\"addStake(uint32)\":{\"notice\":\"add stake value for this paymaster. cancel any pending unlock\"},\"handleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),address)\":{\"notice\":\"Execute the given UserOperation.\"},\"simulatePaymasterValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),uint256)\":{\"notice\":\"Simulate a call to paymaster.verifyPaymasterUserOp do nothing if has no paymaster.\"},\"simulateWalletValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes))\":{\"notice\":\"Simulate a call for wallet.verifyUserOp. Call must not revert.\"},\"stakes(address)\":{\"notice\":\"maps relay managers to their stakes\"},\"unstakeDelayBlocks()\":{\"notice\":\"minimum number of blocks to after 'unlock' before amount can be withdrawn.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/EntryPoint.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./StakeManager.sol\\\";\\nimport \\\"./UserOperation.sol\\\";\\nimport \\\"./IWallet.sol\\\";\\nimport \\\"./IPaymaster.sol\\\";\\n\\ninterface ICreate2Deployer {\\n function deploy(bytes memory _initCode, bytes32 _salt) external returns (address);\\n}\\n\\ncontract EntryPoint is StakeManager {\\n\\n using UserOperationLib for UserOperation;\\n // paymaster locked stake\\n // (actual stake should be higher, to cover actual call cost)\\n uint256 constant PAYMASTER_STAKE = 1 ether;\\n\\n enum PaymentMode {\\n paymasterStake, // if paymaster is set, use paymaster's stake to pay.\\n walletStake, // wallet has enough stake to pay for request.\\n walletEth // wallet has no stake. paying with eth.\\n }\\n\\n uint public immutable perOpOverhead;\\n address public immutable create2factory;\\n\\n event UserOperationEvent(address indexed sender, address indexed paymaster, uint nonce, uint actualGasCost, uint actualGasPrice, bool success);\\n event UserOperationRevertReason(address indexed sender, uint nonce, bytes revertReason);\\n\\n event PaymasterPostOpFailed(address indexed sender, address indexed paymaster, uint nonce, bytes reason);\\n\\n //handleOps reverts with this error struct, to mark the offending op\\n // NOTE: if simulateOp passes successfully, there should be no reason for handleOps to fail on it.\\n // @param opIndex - index into the array of ops to the failed one (in simulateOp, this is always zero)\\n // @param paymaster - if paymaster.verifyPaymasterUserOp fails, this will be the paymaster's address. if verifyUserOp failed,\\n // this value will be zero (since it failed before accessing the paymaster)\\n // @param reason - revert reason\\n // only to aid troubleshooting of wallet/paymaster reverts\\n error FailedOp(uint opIndex, address paymaster, string reason);\\n\\n constructor(address _create2factory, uint _perOpOverhead, uint32 _unstakeDelayBlocks) StakeManager(_unstakeDelayBlocks) {\\n create2factory = _create2factory;\\n perOpOverhead = _perOpOverhead;\\n }\\n\\n receive() external payable {}\\n\\n /**\\n * Execute the given UserOperation.\\n * @param op the operation to execute\\n * @param redeemer the contract to redeem the fee\\n */\\n function handleOp(UserOperation calldata op, address payable redeemer) public {\\n\\n uint preGas = gasleft();\\n\\n (uint256 prefund, PaymentMode paymentMode, bytes memory context) = _validatePrepayment(0, op);\\n uint preOpGas = preGas - gasleft() + perOpOverhead;\\n\\n uint actualGasCost;\\n\\n try this.internalHandleOp(op, context, preOpGas, prefund, paymentMode) returns (uint _actualGasCost) {\\n actualGasCost = _actualGasCost;\\n } catch {\\n uint actualGas = preGas - gasleft() + preOpGas;\\n actualGasCost = handlePostOp(IPaymaster.PostOpMode.postOpReverted, op, context, actualGas, prefund, paymentMode);\\n }\\n\\n redeem(redeemer, actualGasCost);\\n }\\n\\n function redeem(address payable redeemer, uint amount) internal {\\n redeemer.transfer(amount);\\n }\\n\\n function handleOps(UserOperation[] calldata ops, address payable redeemer) public {\\n\\n uint opslen = ops.length;\\n uint256[] memory preOpGas = new uint256[](opslen);\\n bytes32[] memory contexts = new bytes32[](opslen);\\n uint256[] memory prefunds = new uint256[](opslen);\\n PaymentMode[] memory paymentModes = new PaymentMode[](opslen);\\n\\n for (uint i = 0; i < opslen; i++) {\\n uint preGas = gasleft();\\n UserOperation calldata op = ops[i];\\n\\n bytes memory context;\\n bytes32 contextOffset;\\n (prefunds[i], paymentModes[i], context) = _validatePrepayment(i, op);\\n assembly {contextOffset := context}\\n contexts[i] = contextOffset;\\n preOpGas[i] = preGas - gasleft() + perOpOverhead;\\n }\\n\\n uint collected = 0;\\n\\n for (uint i = 0; i < ops.length; i++) {\\n uint preGas = gasleft();\\n UserOperation calldata op = ops[i];\\n bytes32 contextOffset = contexts[i];\\n bytes memory context;\\n assembly {context := contextOffset}\\n uint preOpGasi = preOpGas[i];\\n uint prefundi = prefunds[i];\\n PaymentMode paymentModei = paymentModes[i];\\n\\n try this.internalHandleOp(op, context, preOpGasi, prefundi, paymentModei) returns (uint _actualGasCost) {\\n collected += _actualGasCost;\\n } catch {\\n uint actualGas = preGas - gasleft() + preOpGasi;\\n collected += handlePostOp(IPaymaster.PostOpMode.postOpReverted, op, context, actualGas, prefundi, paymentModei);\\n }\\n }\\n\\n redeem(redeemer, collected);\\n }\\n\\n function internalHandleOp(UserOperation calldata op, bytes calldata context, uint preOpGas, uint prefund, PaymentMode paymentMode) external returns (uint actualGasCost) {\\n uint preGas = gasleft();\\n require(msg.sender == address(this));\\n\\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\\n if (op.callData.length > 0) {\\n\\n (bool success,bytes memory result) = address(op.getSender()).call{gas : op.callGas}(op.callData);\\n if (!success && result.length > 0) {\\n emit UserOperationRevertReason(op.getSender(), op.nonce, result);\\n mode = IPaymaster.PostOpMode.opReverted;\\n }\\n }\\n\\n uint actualGas = preGas - gasleft() + preOpGas;\\n return handlePostOp(mode, op, context, actualGas, prefund, paymentMode);\\n }\\n\\n /**\\n * Simulate a call for wallet.verifyUserOp.\\n * Call must not revert.\\n * @return gasUsedByPayForSelfOp - gas used by the validation, to pass into simulatePaymasterValidation.\\n * The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the wallet's data\\n */\\n function simulateWalletValidation(UserOperation calldata userOp) external returns (uint gasUsedByPayForSelfOp){\\n require(msg.sender == address(0), \\\"must be called off-chain with from=zero-addr\\\");\\n (uint requiredPreFund, PaymentMode paymentMode) = getPaymentInfo(userOp);\\n (gasUsedByPayForSelfOp,) = _validateWalletPrepayment(0, userOp, requiredPreFund, paymentMode);\\n }\\n\\n function getPaymentInfo(UserOperation calldata userOp) internal view returns (uint requiredPrefund, PaymentMode paymentMode) {\\n requiredPrefund = userOp.requiredPreFund(perOpOverhead);\\n if (userOp.hasPaymaster()) {\\n paymentMode = PaymentMode.paymasterStake;\\n } else if (isStaked(userOp.getSender(), requiredPrefund, 0)) {\\n paymentMode = PaymentMode.walletStake;\\n } else {\\n paymentMode = PaymentMode.walletEth;\\n }\\n }\\n\\n /**\\n * Simulate a call to paymaster.verifyPaymasterUserOp\\n * do nothing if has no paymaster.\\n * @param userOp the user operation to validate.\\n * @param gasUsedByPayForSelfOp - the gas returned by simulateWalletValidation, as these 2 calls should share\\n * the same userOp.validationGas quota.\\n * The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the paymaster's data\\n */\\n function simulatePaymasterValidation(UserOperation calldata userOp, uint gasUsedByPayForSelfOp) external view returns (bytes memory context, uint gasUsedByPayForOp){\\n (uint requiredPreFund, PaymentMode paymentMode) = getPaymentInfo(userOp);\\n if (paymentMode != PaymentMode.paymasterStake) {\\n return (\\\"\\\", 0);\\n }\\n return _validatePaymasterPrepayment(0, userOp, requiredPreFund, gasUsedByPayForSelfOp);\\n }\\n\\n // get the sender address, or use \\\"create2\\\" to create it.\\n // note that the gas allocation for this creation is deterministic (by the size of callData),\\n // so it is not checked on-chain, and adds to the gas used by verifyUserOp\\n function _createSenderIfNeeded(UserOperation calldata op) internal {\\n if (op.initCode.length != 0) {\\n //its a create operation. run the create2\\n // note that we're still under the gas limit of validate, so probably\\n // this create2 creates a proxy account.\\n // appending signer makes the request unique, so no one else can make this request.\\n //nonce is meaningless during create, so we re-purpose it as salt\\n address sender1 = ICreate2Deployer(create2factory).deploy(op.initCode, bytes32(op.nonce));\\n require(sender1 != address(0), \\\"create2 failed\\\");\\n require(sender1 == op.getSender(), \\\"sender doesn't match create2 address\\\");\\n }\\n }\\n\\n //get counterfactual sender address.\\n // use the initCode and salt in the UserOperation tot create this sender contract\\n function getSenderAddress(bytes memory initCode, uint _salt) public view returns (address) {\\n bytes32 hash = keccak256(\\n abi.encodePacked(\\n bytes1(0xff),\\n address(create2factory),\\n _salt,\\n keccak256(initCode)\\n )\\n );\\n\\n // NOTE: cast last 20 bytes of hash to address\\n return address(uint160(uint256(hash)));\\n }\\n\\n //call wallet.verifyUserOp, and validate that it paid as needed.\\n // return actual value sent from wallet to \\\"this\\\"\\n function _validateWalletPrepayment(uint opIndex, UserOperation calldata op, uint requiredPrefund, PaymentMode paymentMode) internal returns (uint gasUsedByPayForSelfOp, uint prefund) {\\n uint preGas = gasleft();\\n _createSenderIfNeeded(op);\\n uint preBalance = address(this).balance;\\n uint requiredEthPrefund = 0;\\n if (paymentMode == PaymentMode.walletEth) {\\n requiredEthPrefund = requiredPrefund;\\n } else if (paymentMode == PaymentMode.walletStake) {\\n _prefundFromSender(op, requiredPrefund);\\n } else {\\n // paymaster pays in handlePostOp\\n }\\n try IWallet(op.getSender()).verifyUserOp{gas : op.verificationGas}(op, requiredEthPrefund) {\\n } catch Error(string memory revertReason) {\\n revert FailedOp(opIndex, address(0), revertReason);\\n } catch {\\n revert FailedOp(opIndex, address(0), \\\"\\\");\\n }\\n uint actualEthPrefund = address(this).balance - preBalance;\\n\\n if (paymentMode == PaymentMode.walletEth) {\\n if (actualEthPrefund < requiredEthPrefund) {\\n revert FailedOp(opIndex, address(0), \\\"wallet didn't pay prefund\\\");\\n }\\n prefund = actualEthPrefund;\\n } else if (paymentMode == PaymentMode.walletStake) {\\n if (actualEthPrefund != 0) {\\n revert FailedOp(opIndex, address(0), \\\"using wallet stake but wallet paid eth\\\");\\n }\\n prefund = requiredPrefund;\\n } else {\\n if (actualEthPrefund != 0) {\\n revert FailedOp(opIndex, address(0), \\\"has paymaster but wallet paid\\\");\\n }\\n prefund = requiredPrefund;\\n }\\n\\n gasUsedByPayForSelfOp = preGas - gasleft();\\n }\\n\\n //validate paymaster.verifyPaymasterUserOp\\n function _validatePaymasterPrepayment(uint opIndex, UserOperation calldata op, uint requiredPreFund, uint gasUsedByPayForSelfOp) internal view returns (bytes memory context, uint gasUsedByPayForOp) {\\n uint preGas = gasleft();\\n if (!isValidStake(op, requiredPreFund)) {\\n revert FailedOp(opIndex, op.paymaster, \\\"not enough stake\\\");\\n }\\n //no pre-pay from paymaster\\n uint gas = op.verificationGas - gasUsedByPayForSelfOp;\\n try IPaymaster(op.paymaster).verifyPaymasterUserOp{gas : gas}(op, requiredPreFund) returns (bytes memory _context){\\n context = _context;\\n } catch Error(string memory revertReason) {\\n revert FailedOp(opIndex, op.paymaster, revertReason);\\n } catch {\\n revert FailedOp(opIndex, op.paymaster, \\\"\\\");\\n }\\n gasUsedByPayForOp = preGas - gasleft();\\n }\\n\\n function _validatePrepayment(uint opIndex, UserOperation calldata userOp) private returns (uint prefund, PaymentMode paymentMode, bytes memory context){\\n\\n uint preGas = gasleft();\\n uint gasUsedByPayForSelfOp;\\n uint requiredPreFund;\\n (requiredPreFund, paymentMode) = getPaymentInfo(userOp);\\n\\n (gasUsedByPayForSelfOp, prefund) = _validateWalletPrepayment(opIndex, userOp, requiredPreFund, paymentMode);\\n\\n uint gasUsedByPayForOp = 0;\\n if (paymentMode == PaymentMode.paymasterStake) {\\n (context, gasUsedByPayForOp) = _validatePaymasterPrepayment(opIndex, userOp, requiredPreFund, gasUsedByPayForSelfOp);\\n } else {\\n context = \\\"\\\";\\n }\\n uint gasUsed = preGas - gasleft();\\n\\n if (userOp.verificationGas < gasUsed) {\\n revert FailedOp(opIndex, userOp.paymaster, \\\"Used more than verificationGas\\\");\\n }\\n }\\n\\n function getPaymastersStake(address[] calldata paymasters) external view returns (uint[] memory _stakes) {\\n _stakes = new uint[](paymasters.length);\\n for (uint i = 0; i < paymasters.length; i++) {\\n _stakes[i] = stakes[paymasters[i]].stake;\\n }\\n }\\n\\n function handlePostOp(IPaymaster.PostOpMode mode, UserOperation calldata op, bytes memory context, uint actualGas, uint prefund, PaymentMode paymentMode) private returns (uint actualGasCost) {\\n uint preGas = gasleft();\\n uint gasPrice = UserOperationLib.gasPrice(op);\\n actualGasCost = actualGas * gasPrice;\\n if (paymentMode != PaymentMode.paymasterStake) {\\n if (prefund < actualGasCost) {\\n revert (\\\"wallet prefund below actualGasCost\\\");\\n }\\n uint refund = prefund - actualGasCost;\\n if (paymentMode == PaymentMode.walletStake) {\\n _refundSenderStake(op, refund);\\n } else {\\n _refundSender(op, refund);\\n }\\n } else {\\n if (context.length > 0) {\\n //if paymaster.postOp reverts:\\n // - emit a message (just for sake of debugging of this poor paymaster)\\n // - paymaster still pays (from its stake)\\n try IPaymaster(op.paymaster).postOp(mode, context, actualGasCost) {}\\n catch (bytes memory errdata) {\\n emit PaymasterPostOpFailed(op.getSender(), op.paymaster, op.nonce, errdata);\\n }\\n }\\n //paymaster pays for full gas, including for postOp (and revert event)\\n actualGas += preGas - gasleft();\\n actualGasCost = actualGas * gasPrice;\\n //paymaster balance known to be high enough, and to be locked for this block\\n stakes[op.paymaster].stake -= uint96(actualGasCost);\\n }\\n _emitLog(op, actualGasCost, gasPrice, mode == IPaymaster.PostOpMode.opSucceeded);\\n }\\n\\n function _emitLog(UserOperation calldata op, uint actualGasCost, uint gasPrice, bool success) internal {\\n emit UserOperationEvent(op.getSender(), op.paymaster, op.nonce, actualGasCost, gasPrice, success);\\n }\\n\\n function _prefundFromSender(UserOperation calldata userOp, uint requiredPrefund) internal {\\n stakes[userOp.getSender()].stake -= uint96(requiredPrefund);\\n }\\n\\n function _refundSender(UserOperation calldata userOp, uint refund) internal {\\n //NOTE: deliberately ignoring revert: wallet should accept refund.\\n bool sendOk = payable(userOp.getSender()).send(refund);\\n (sendOk);\\n }\\n function _refundSenderStake(UserOperation calldata userOp, uint refund) internal {\\n stakes[userOp.getSender()].stake += uint96(refund);\\n }\\n\\n function isValidStake(UserOperation calldata userOp, uint requiredPreFund) internal view returns (bool) {\\n return isPaymasterStaked(userOp.paymaster, PAYMASTER_STAKE + requiredPreFund);\\n }\\n\\n function isPaymasterStaked(address paymaster, uint stake) public view returns (bool) {\\n return isStaked(paymaster, stake, unstakeDelayBlocks);\\n }\\n\\n function isContractDeployed(address addr) external view returns (bool) {\\n bytes32 hash;\\n assembly {\\n hash := extcodehash(addr)\\n }\\n return hash != bytes32(0);\\n }\\n}\\n\\n\",\"keccak256\":\"0x8b15a6fcb66f95fc079400ff2b38de805405ce6c23c4bbbc1bcd24bb6cabefb0\",\"license\":\"GPL-3.0\"},\"contracts/IPaymaster.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\ninterface IPaymaster {\\n\\n enum PostOpMode {\\n opSucceeded, // user op succeeded\\n opReverted, // user op reverted. still has to pay for gas.\\n postOpReverted //user op succeeded, but caused postOp to revert. Now its a 2nd call, after user's op was deliberately reverted.\\n }\\n // payment validation: check if paymaster agree to pay (using its stake)\\n // revert to reject this request.\\n // actual payment is done after postOp is called, by deducting actual call cost form the paymaster's stake.\\n // @param userOp the user operation\\n // @param maxcost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\\n // @returns context value to send to a postOp\\n // zero length to signify postOp is not required.\\n function verifyPaymasterUserOp(UserOperation calldata userOp, uint maxcost) external view returns (bytes memory context);\\n\\n // post-operation handler.\\n // @param mode\\n // opSucceeded - user operation succeeded.\\n // opReverted - user op reverted. still has to pay for gas.\\n // postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\\n // Now this is the 2nd call, after user's op was deliberately reverted.\\n // @param context - the context value returned by verifyPaymasterUserOp\\n // @param actualGasCost - actual gas used so far (without this postOp call).\\n function postOp(PostOpMode mode, bytes calldata context, uint actualGasCost) external;\\n}\\n\",\"keccak256\":\"0xef51907c5520d22e74cc7804b30634cdc6d2cbf2fe96b77d0b6785a53c4545a5\",\"license\":\"GPL-3.0\"},\"contracts/IWallet.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\ninterface IWallet {\\n\\n // validate user's signature and nonce\\n // @param requiredPrefund how much this wallet should pre-fund the transaction.\\n // @note that after execution, the excess is sent back to the wallet.\\n // @note if requiredPrefund is zero, the wallet MUST NOT send anything (the paymaster pays)\\n function verifyUserOp(UserOperation calldata userOp, uint requiredPrefund) external;\\n}\\n\",\"keccak256\":\"0x29f98a4e6033cd10007dcc9b569fda950413cc91d8560a67f20a35e8185c9228\",\"license\":\"GPL-3.0\"},\"contracts/StakeManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-only\\npragma solidity ^0.8;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\ncontract StakeManager {\\n\\n /// minimum number of blocks to after 'unlock' before amount can be withdrawn.\\n uint32 immutable public unstakeDelayBlocks;\\n\\n constructor(uint32 _unstakeDelayBlocks) {\\n unstakeDelayBlocks = _unstakeDelayBlocks;\\n }\\n\\n event StakeAdded(\\n address indexed paymaster,\\n uint256 totalStake,\\n uint256 unstakeDelayBlocks\\n );\\n\\n /// Emitted once a stake is scheduled for withdrawal\\n event StakeUnlocking(\\n address indexed paymaster,\\n uint256 withdrawBlock\\n );\\n\\n event StakeWithdrawn(\\n address indexed paymaster,\\n address withdrawAddress,\\n uint256 amount\\n );\\n\\n /// @param stake - amount of ether staked for this paymaster\\n /// @param withdrawStake - once 'unlocked' the value is no longer staked.\\n /// @param withdrawBlock - first block number 'withdraw' will be callable, or zero if the unlock has not been called\\n struct StakeInfo {\\n uint96 stake;\\n uint32 unstakeDelayBlocks;\\n uint96 withdrawStake;\\n uint32 withdrawBlock;\\n }\\n\\n /// maps relay managers to their stakes\\n mapping(address => StakeInfo) public stakes;\\n\\n function getStakeInfo(address paymaster) external view returns (StakeInfo memory stakeInfo) {\\n return stakes[paymaster];\\n }\\n\\n /**\\n * add a deposit (just like stake, but with lock=0\\n * cancel any pending unlock\\n */\\n function addDeposit() external payable {\\n addStake(0);\\n }\\n\\n //add deposit to another account (doesn't change lock status)\\n function addDepositTo(address target) external payable {\\n stakes[target].stake += uint96(msg.value);\\n }\\n\\n /**\\n * add stake value for this paymaster.\\n * cancel any pending unlock\\n */\\n function addStake(uint32 _unstakeDelayBlocks) public payable {\\n require(_unstakeDelayBlocks >= stakes[msg.sender].unstakeDelayBlocks, \\\"cannot decrease unstake blocks\\\");\\n uint96 stake = uint96(stakes[msg.sender].stake + msg.value + stakes[msg.sender].withdrawStake);\\n stakes[msg.sender] = StakeInfo(\\n stake,\\n _unstakeDelayBlocks,\\n 0,\\n 0);\\n emit StakeAdded(msg.sender, stake, _unstakeDelayBlocks);\\n }\\n\\n function unlockStake() external {\\n StakeInfo storage info = stakes[msg.sender];\\n require(info.withdrawBlock == 0, \\\"already pending\\\");\\n require(info.stake != 0 && info.unstakeDelayBlocks != 0, \\\"no stake to unlock\\\");\\n uint32 withdrawBlock = uint32(block.number) + info.unstakeDelayBlocks;\\n info.withdrawBlock = withdrawBlock;\\n info.withdrawStake = info.stake;\\n info.stake = 0;\\n emit StakeUnlocking(msg.sender, withdrawBlock);\\n }\\n\\n function withdrawStake(address payable withdrawAddress) external {\\n StakeInfo memory info = stakes[msg.sender];\\n if (info.unstakeDelayBlocks != 0) {\\n require(info.withdrawStake > 0, \\\"no unlocked stake\\\");\\n require(info.withdrawBlock <= block.number, \\\"Withdrawal is not due\\\");\\n }\\n uint256 amount = info.withdrawStake + info.stake;\\n stakes[msg.sender] = StakeInfo(0, info.unstakeDelayBlocks, 0, 0);\\n withdrawAddress.transfer(amount);\\n emit StakeWithdrawn(msg.sender, withdrawAddress, amount);\\n }\\n\\n function isStaked(address paymaster, uint requiredStake, uint requiredDelayBlocks) public view returns (bool) {\\n StakeInfo memory stakeInfo = stakes[paymaster];\\n return stakeInfo.stake >= requiredStake && stakeInfo.unstakeDelayBlocks >= requiredDelayBlocks;\\n }\\n}\\n\",\"keccak256\":\"0x238f903aceaaa89fd289d99c16ff660b6f911837f50ccf3fc3bb94653024b1aa\",\"license\":\"GPL-3.0-only\"},\"contracts/UserOperation.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n struct UserOperation {\\n\\n address sender;\\n uint256 nonce;\\n bytes initCode;\\n bytes callData;\\n uint callGas;\\n uint verificationGas;\\n uint preVerificationGas;\\n uint maxFeePerGas;\\n uint maxPriorityFeePerGas;\\n address paymaster;\\n bytes paymasterData;\\n bytes signature;\\n }\\n\\nlibrary UserOperationLib {\\n\\n function getSender(UserOperation calldata userOp) internal view returns (address ret) {\\n assembly {ret := calldataload(userOp)}\\n }\\n\\n //relayer/miner might submit the TX with higher priorityFee, but the user should not\\n // pay above what he signed for.\\n function gasPrice(UserOperation calldata userOp) internal view returns (uint) {\\n unchecked {\\n return min(userOp.maxFeePerGas, userOp.maxPriorityFeePerGas + block.basefee);\\n }\\n }\\n\\n function requiredGas(UserOperation calldata userOp) internal pure returns (uint) {\\n unchecked {\\n return userOp.callGas + userOp.verificationGas + userOp.preVerificationGas;\\n }\\n }\\n\\n function requiredPreFund(UserOperation calldata userOp, uint overhead) internal view returns (uint prefund) {\\n return (requiredGas(userOp) + overhead) * gasPrice(userOp);\\n }\\n\\n function hasPaymaster(UserOperation calldata userOp) internal pure returns (bool) {\\n return userOp.paymaster != address(0);\\n }\\n\\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\\n //lighter signature scheme. must match UserOp.ts#packUserOp\\n bytes calldata sig = userOp.signature;\\n assembly {\\n let ofs := userOp\\n let len := sub(sub(sig.offset, ofs), 32)\\n ret := mload(0x40)\\n mstore(0x40, add(ret, add(len, 32)))\\n mstore(ret, len)\\n calldatacopy(add(ret, 32), ofs, len)\\n }\\n return ret;\\n\\n //TODO: eip712-style ?\\n return abi.encode(\\n userOp.sender,\\n userOp.nonce,\\n keccak256(userOp.initCode),\\n keccak256(userOp.callData),\\n userOp.callGas,\\n userOp.verificationGas,\\n userOp.preVerificationGas,\\n userOp.maxFeePerGas,\\n userOp.maxPriorityFeePerGas,\\n userOp.paymaster,\\n keccak256(userOp.paymasterData)\\n );\\n }\\n\\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(pack(userOp))));\\n }\\n\\n function min(uint a, uint b) internal pure returns (uint) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0x7ea8383b9bbd8cfa5a96f59e1f37c20a681daa798b80d67eb52ade3c53f3ea30\",\"license\":\"GPL-3.0\"},\"hardhat/console.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\",\"keccak256\":\"0x72b6a1d297cd3b033d7c2e4a7e7864934bb767db6453623f1c3082c6534547f4\",\"license\":\"MIT\"}},\"version\":1}",
+ "bytecode": "0x60e06040523480156200001157600080fd5b5060405162002cc738038062002cc7833981016040819052620000349162000060565b60e01b6001600160e01b03191660805260609190911b6001600160601b03191660c05260a052620000bb565b6000806000606084860312156200007657600080fd5b83516001600160a01b03811681146200008e57600080fd5b60208501516040860151919450925063ffffffff81168114620000b057600080fd5b809150509250925092565b60805160e01c60a05160c05160601c612bac6200011b60003960008181610156015281816103e50152611f350152600081816102af01528181610a0a01528181611330015261187101526000818161056e01526107f50152612bac6000f3fe6080604052600436106101235760003560e01c8063af2ed7d7116100a0578063c345315311610064578063c345315314610446578063dbbabd6a1461053c578063e7c350e31461055c578063f20751eb146105a5578063f3737f19146105c657600080fd5b8063af2ed7d71461033a578063bb9fe6bf1461035a578063bf55512e1461036f578063c23a5cea1461038f578063c31e4354146103af57600080fd5b80632815c17b116100e75780632815c17b146102755780634a58db1914610295578063643407ce1461029d578063739b8950146102df578063828190131461030c57600080fd5b80630396cb601461012f5780630bfb68471461014457806316934fc4146101955780631c112a44146102255780631fa75c861461025557600080fd5b3661012a57005b600080fd5b61014261013d366004612540565b6105d9565b005b34801561015057600080fd5b506101787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a157600080fd5b506101ee6101b0366004612161565b6000602081905290815260409020546001600160601b038082169163ffffffff600160601b8204811692600160801b83041691600160e01b90041684565b604080516001600160601b03958616815263ffffffff9485166020820152949092169184019190915216606082015260800161018c565b34801561023157600080fd5b506102456102403660046121c7565b610764565b604051901515815260200161018c565b34801561026157600080fd5b5061024561027036600461219b565b6107ec565b34801561028157600080fd5b5061014261029036600461223d565b610826565b610142610c24565b3480156102a957600080fd5b506102d17f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161018c565b3480156102eb57600080fd5b506102ff6102fa3660046121fc565b610c30565b60405161018c91906126dd565b34801561031857600080fd5b5061032c6103273660046124e3565b610d09565b60405161018c929190612745565b34801561034657600080fd5b506102d161035536600461242a565b610d70565b34801561036657600080fd5b50610142610ee2565b34801561037b57600080fd5b506102d161038a36600461239d565b611055565b34801561039b57600080fd5b506101426103aa366004612161565b6110e0565b3480156103bb57600080fd5b506101786103ca366004612314565b8151602092830120604080516001600160f81b0319818601527f000000000000000000000000000000000000000000000000000000000000000060601b6bffffffffffffffffffffffff191660218201526035810193909352605580840192909252805180840390920182526075909201909152805191012090565b34801561045257600080fd5b506104eb610461366004612161565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b031660009081526020818152604091829020825160808101845290546001600160601b03808216835263ffffffff600160601b8304811694840194909452600160801b82041693820193909352600160e01b90920416606082015290565b60405161018c919060006080820190506001600160601b03808451168352602084015163ffffffff808216602086015282604087015116604086015280606087015116606086015250505092915050565b34801561054857600080fd5b506101426105573660046123d9565b611311565b34801561056857600080fd5b506105907f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161018c565b3480156105b157600080fd5b506102456105c0366004612161565b3f151590565b6101426105d4366004612161565b61142b565b3360009081526020819052604090205463ffffffff600160601b9091048116908216101561064e5760405162461bcd60e51b815260206004820152601e60248201527f63616e6e6f7420646563726561736520756e7374616b6520626c6f636b73000060448201526064015b60405180910390fd5b336000908152602081905260408120546001600160601b03600160801b820481169161067c9134911661290f565b610686919061290f565b604080516080810182526001600160601b0383811680835263ffffffff878116602080860182815260008789018181526060890182815233808452838652928b902099518a54945192519151908a166001600160801b031990951694909417600160601b92881692909202919091176001600160801b0316600160801b91909816026001600160e01b031696909617600160e01b91909416029290921790945584519182528101929092529293507f270d6dd254edd1d985c81cf7861b8f28fb06b6d719df04d90464034d4341244091015b60405180910390a25050565b6001600160a01b038316600090815260208181526040808320815160808101835290546001600160601b0380821680845263ffffffff600160601b8404811696850196909652600160801b830490911693830193909352600160e01b9004909216606083015284118015906107e3575082816020015163ffffffff1610155b95945050505050565b600061081f83837f000000000000000000000000000000000000000000000000000000000000000063ffffffff16610764565b9392505050565b816000816001600160401b0381111561084157610841612a88565b60405190808252806020026020018201604052801561086a578160200160208202803683370190505b5090506000826001600160401b0381111561088757610887612a88565b6040519080825280602002602001820160405280156108b0578160200160208202803683370190505b5090506000836001600160401b038111156108cd576108cd612a88565b6040519080825280602002602001820160405280156108f6578160200160208202803683370190505b5090506000846001600160401b0381111561091357610913612a88565b60405190808252806020026020018201604052801561093c578160200160208202803683370190505b50905060005b85811015610a735760005a9050368a8a8481811061096257610962612a72565b90506020028101906109749190612882565b9050606060006109848584611483565b89888151811061099657610996612a72565b602002602001018989815181106109af576109af612a72565b602002602001018296508360028111156109cb576109cb612a5c565b60028111156109dc576109dc612a5c565b81525083815250505050819050808886815181106109fc576109fc612a72565b6020026020010181815250507f00000000000000000000000000000000000000000000000000000000000000005a610a349086612990565b610a3e919061290f565b898681518110610a5057610a50612a72565b602002602001018181525050505050508080610a6b90612a2b565b915050610942565b506000805b88811015610c0e5760005a9050368b8b84818110610a9857610a98612a72565b9050602002810190610aaa9190612882565b90506000878481518110610ac057610ac0612a72565b60200260200101519050606081905060008a8681518110610ae357610ae3612a72565b602002602001015190506000898781518110610b0157610b01612a72565b602002602001015190506000898881518110610b1f57610b1f612a72565b60200260200101519050306001600160a01b031663af2ed7d787868686866040518663ffffffff1660e01b8152600401610b5d959493929190612799565b602060405180830381600087803b158015610b7757600080fd5b505af1925050508015610ba7575060408051601f3d908101601f19168201909252610ba491810190612527565b60015b610be6576000835a610bb9908a612990565b610bc3919061290f565b9050610bd460028887848787611589565b610bde908b61290f565b995050610bf4565b610bf0818b61290f565b9950505b505050505050508080610c0690612a2b565b915050610a78565b50610c19878261182d565b505050505050505050565b610c2e60006105d9565b565b6060816001600160401b03811115610c4a57610c4a612a88565b604051908082528060200260200182016040528015610c73578160200160208202803683370190505b50905060005b82811015610d0257600080858584818110610c9657610c96612a72565b9050602002016020810190610cab9190612161565b6001600160a01b0316815260208101919091526040016000205482516001600160601b0390911690839083908110610ce557610ce5612a72565b602090810291909101015280610cfa81612a2b565b915050610c79565b5092915050565b60606000806000610d1986611868565b90925090506000816002811115610d3257610d32612a5c565b14610d555760006040518060200160405280600081525090935093505050610d69565b610d6260008784886118cf565b9350935050505b9250929050565b6000805a9050333014610d8257600080fd5b600080610d9260608b018b61283c565b90501115610e74576000808a356001600160a01b031660808c0135610dba60608e018e61283c565b604051610dc89291906126cd565b60006040518083038160008787f1925050503d8060008114610e06576040519150601f19603f3d011682016040523d82523d6000602084013e610e0b565b606091505b509150915081158015610e1f575060008151115b15610e71578a356001600160a01b03167fbe4889eb241fb33bc0e9873f6e442f4c5dc653a55e7ad8bca2f001c9b3d818fb8c6020013583604051610e64929190612823565b60405180910390a2600192505b50505b6000865a610e829085612990565b610e8c919061290f565b9050610ed4828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508792508c91508b9050611589565b9a9950505050505050505050565b3360009081526020819052604090208054600160e01b900463ffffffff1615610f3f5760405162461bcd60e51b815260206004820152600f60248201526e616c72656164792070656e64696e6760881b6044820152606401610645565b80546001600160601b031615801590610f6557508054600160601b900463ffffffff1615155b610fa65760405162461bcd60e51b81526020600482015260126024820152716e6f207374616b6520746f20756e6c6f636b60701b6044820152606401610645565b8054600090610fc290600160601b900463ffffffff1643612927565b82546001600160801b0381166bffffffffffffffffffffffff60801b19600160e01b63ffffffff8516908102918216929092176001600160601b039384169190931617600160801b02919091176bffffffffffffffffffffffff1916845560405190815290915033907fab3a43860ac8cdb29929ba1a1f556b4decf9617f4811c190010e1672e55839b190602001610758565b600033156110ba5760405162461bcd60e51b815260206004820152602c60248201527f6d7573742062652063616c6c6564206f66662d636861696e207769746820667260448201526b37b69ebd32b93796b0b2323960a11b6064820152608401610645565b6000806110c684611868565b915091506110d76000858484611aab565b50949350505050565b3360009081526020818152604091829020825160808101845290546001600160601b03808216835263ffffffff600160601b83048116948401859052600160801b830490911694830194909452600160e01b90049092166060830152156111e457600081604001516001600160601b0316116111925760405162461bcd60e51b81526020600482015260116024820152706e6f20756e6c6f636b6564207374616b6560781b6044820152606401610645565b43816060015163ffffffff1611156111e45760405162461bcd60e51b81526020600482015260156024820152745769746864726177616c206973206e6f742064756560581b6044820152606401610645565b805160408201516000916111f79161294f565b60408051608081018252600080825260208681015163ffffffff9081168285019081528486018481526060860185815233865293859052868520955186549251915194518416600160e01b026001600160e01b036001600160601b03968716600160801b02166001600160801b0393909516600160601b026001600160801b031990941691861691909117929092171691909117179092559151921692506001600160a01b0385169183156108fc0291849190818181858888f193505050501580156112c7573d6000803e3d6000fd5b50604080516001600160a01b03851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a2505050565b60005a90506000806000611326600087611483565b92509250925060007f00000000000000000000000000000000000000000000000000000000000000005a61135a9087612990565b611364919061290f565b60405163af2ed7d760e01b8152909150600090309063af2ed7d790611395908b90879087908b908b90600401612799565b602060405180830381600087803b1580156113af57600080fd5b505af19250505080156113df575060408051601f3d908101601f191682019092526113dc91810190612527565b60015b611414576000825a6113f19089612990565b6113fb919061290f565b905061140c60028a86848a8a611589565b915050611417565b90505b611421878261182d565b5050505050505050565b6001600160a01b0381166000908152602081905260408120805434929061145c9084906001600160601b031661294f565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555050565b600080606060005a905060008061149987611868565b955090506114a988888388611aab565b965091506000808660028111156114c2576114c2612a5c565b14156114de576114d4898984866118cf565b90955090506114f1565b6040518060200160405280600081525094505b60005a6114fe9086612990565b9050808960a00135101561157d578961151f6101408b016101208c01612161565b60405162fa072b60e01b815260048101929092526001600160a01b0316602482015260606044820152601e60648201527f55736564206d6f7265207468616e20766572696669636174696f6e4761730000608482015260a401610645565b50505050509250925092565b6000805a9050600061159a88611d77565b90506115a68187612971565b925060008460028111156115bc576115bc612a5c565b14611663578285101561161c5760405162461bcd60e51b815260206004820152602260248201527f77616c6c65742070726566756e642062656c6f772061637475616c476173436f6044820152611cdd60f21b6064820152608401610645565b60006116288487612990565b9050600185600281111561163e5761163e612a5c565b14156116535761164e8982611d94565b61165d565b61165d8982611dee565b50611801565b86511561176f5761167c61014089016101208a01612161565b6001600160a01b031663a9a234098a89866040518463ffffffff1660e01b81526004016116ab93929190612767565b600060405180830381600087803b1580156116c557600080fd5b505af19250505080156116d6575060015b61176f573d808015611704576040519150601f19603f3d011682016040523d82523d6000602084013e611709565b606091505b5061171c6101408a016101208b01612161565b6001600160a01b031689356001600160a01b03167f45197bfe91c32368fd75a4fcab42a1eff7699e79df0e171a343537be7657efb68b6020013584604051611765929190612823565b60405180910390a3505b5a61177a9083612990565b611784908761290f565b95506117908187612971565b9250826000806117a86101408c016101208d01612161565b6001600160a01b031681526020810191909152604001600090812080549091906117dc9084906001600160601b03166129a7565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b61182188848360008d600281111561181b5761181b612a5c565b14611e1b565b50509695505050505050565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611863573d6000803e3d6000fd5b505050565b600080611895837f0000000000000000000000000000000000000000000000000000000000000000611e97565b91506118a083611ec6565b156118ad57506000915091565b6118ba8335836000610764565b156118c757506001915091565b506002915091565b60606000805a90506118e18686611eec565b61194957866118f861014088016101208901612161565b60405162fa072b60e01b815260048101929092526001600160a01b0316602482015260606044820152601060648201526f6e6f7420656e6f756768207374616b6560801b608482015260a401610645565b60006119598560a0890135612990565b905061196d61014088016101208901612161565b6001600160a01b03166380fd44d58289896040518463ffffffff1660e01b815260040161199b9291906127e6565b60006040518083038187803b1580156119b357600080fd5b5086fa935050505080156119e957506040513d6000823e601f3d908101601f191682016040526119e69190810190612293565b60015b611a91576119f5612a9e565b806308c379a01415611a445750611a0a612aba565b80611a155750611a46565b88611a286101408a016101208b01612161565b8260405162fa072b60e01b8152600401610645939291906127f9565b505b87611a5961014089016101208a01612161565b60405162fa072b60e01b815260048101929092526001600160a01b031660248201526060604482015260006064820152608401610645565b93505a611a9e9083612990565b9250505094509492505050565b60008060005a9050611abc86611f15565b4760006002866002811115611ad357611ad3612a5c565b1415611ae0575085611b04565b6001866002811115611af457611af4612a5c565b1415611b0457611b04888861209d565b6040516307dfd9cf60e51b81526001600160a01b038935169063fbfb39e09060a08b013590611b39908c9086906004016127e6565b600060405180830381600088803b158015611b5357600080fd5b5087f193505050508015611b65575060015b611be257611b71612a9e565b806308c379a01415611bb05750611b86612aba565b80611b915750611bb2565b8960008260405162fa072b60e01b8152600401610645939291906127f9565b505b60405162fa072b60e01b8152600481018a9052600060248201819052606060448301526064820152608401610645565b6000611bee8347612990565b90506002876002811115611c0457611c04612a5c565b1415611c705781811015611c685760405162fa072b60e01b8152600481018b90526000602482015260606044820152601960648201527f77616c6c6574206469646e2774207061792070726566756e6400000000000000608482015260a401610645565b809450611d5d565b6001876002811115611c8457611c84612a5c565b1415611cfd578015611cf55760405162fa072b60e01b8152600481018b90526000602482015260606044820152602660648201527f7573696e672077616c6c6574207374616b65206275742077616c6c65742070616084820152650d2c840cae8d60d31b60a482015260c401610645565b879450611d5d565b8015611d595760405162fa072b60e01b8152600481018b90526000602482015260606044820152601d60648201527f686173207061796d6173746572206275742077616c6c65742070616964000000608482015260a401610645565b8794505b5a611d689085612990565b95505050505094509492505050565b6000611d8e8260e0013548846101000135016120cf565b92915050565b6001600160a01b0382351660009081526020819052604081208054839290611dc69084906001600160601b031661294f565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050565b6040516000906001600160a01b038435169083156108fc0290849084818181858888f15050505050505050565b611e2d61014085016101208601612161565b6001600160a01b03168435604080516020808901358252810187905290810185905283151560608201526001600160a01b0391909116907fc27a60e61c14607957b41fa2dad696de47b2d80e390d0eaaf1514c0cd20342939060800160405180910390a350505050565b6000611ea283611d77565b611ebc83608086013560a08701350160c08701350161290f565b61081f9190612971565b600080611edb61014084016101208501612161565b6001600160a01b0316141592915050565b600061081f611f0361014085016101208601612161565b61027084670de0b6b3a764000061290f565b611f22604082018261283c565b15905061209a5760006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016634af63f02611f67604085018561283c565b6040516001600160e01b031960e085901b168152611f8f929190602088013590600401612721565b602060405180830381600087803b158015611fa957600080fd5b505af1158015611fbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe1919061217e565b90506001600160a01b03811661202a5760405162461bcd60e51b815260206004820152600e60248201526d18dc99585d194c8819985a5b195960921b6044820152606401610645565b81356001600160a01b0316816001600160a01b0316146120985760405162461bcd60e51b8152602060048201526024808201527f73656e64657220646f65736e2774206d617463682063726561746532206164646044820152637265737360e01b6064820152608401610645565b505b50565b6001600160a01b0382351660009081526020819052604081208054839290611dc69084906001600160601b03166129a7565b60008183106120de578161081f565b5090919050565b80356120f081612b61565b919050565b60008083601f84011261210757600080fd5b5081356001600160401b0381111561211e57600080fd5b6020830191508360208260051b8501011115610d6957600080fd5b8035600381106120f057600080fd5b6000610180828403121561215b57600080fd5b50919050565b60006020828403121561217357600080fd5b813561081f81612b61565b60006020828403121561219057600080fd5b815161081f81612b61565b600080604083850312156121ae57600080fd5b82356121b981612b61565b946020939093013593505050565b6000806000606084860312156121dc57600080fd5b83356121e781612b61565b95602085013595506040909401359392505050565b6000806020838503121561220f57600080fd5b82356001600160401b0381111561222557600080fd5b612231858286016120f5565b90969095509350505050565b60008060006040848603121561225257600080fd5b83356001600160401b0381111561226857600080fd5b612274868287016120f5565b909450925050602084013561228881612b61565b809150509250925092565b6000602082840312156122a557600080fd5b81516001600160401b038111156122bb57600080fd5b8201601f810184136122cc57600080fd5b80516122d7816128a3565b6040516122e482826129ff565b8281528660208486010111156122f957600080fd5b61230a8360208301602087016129cf565b9695505050505050565b6000806040838503121561232757600080fd5b82356001600160401b0381111561233d57600080fd5b8301601f8101851361234e57600080fd5b8035612359816128a3565b60405161236682826129ff565b82815287602084860101111561237b57600080fd5b8260208501602083013760006020938201840152979590910135955050505050565b6000602082840312156123af57600080fd5b81356001600160401b038111156123c557600080fd5b6123d184828501612148565b949350505050565b600080604083850312156123ec57600080fd5b82356001600160401b0381111561240257600080fd5b61240e85828601612148565b925050602083013561241f81612b61565b809150509250929050565b60008060008060008060a0878903121561244357600080fd5b86356001600160401b038082111561245a57600080fd5b6124668a838b01612148565b9750602089013591508082111561247c57600080fd5b818901915089601f83011261249057600080fd5b81358181111561249f57600080fd5b8a60208285010111156124b157600080fd5b60208301975080965050505060408701359250606087013591506124d760808801612139565b90509295509295509295565b600080604083850312156124f657600080fd5b82356001600160401b0381111561250c57600080fd5b61251885828601612148565b95602094909401359450505050565b60006020828403121561253957600080fd5b5051919050565b60006020828403121561255257600080fd5b813563ffffffff8116811461081f57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526125a78160208601602086016129cf565b601f01601f19169290920160200192915050565b60006101806125da846125cd856120e5565b6001600160a01b03169052565b602083013560208501526125f160408401846128ca565b8260408701526126048387018284612566565b9250505061261560608401846128ca565b8583036060870152612628838284612566565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e085015261010080840135818601525061012061266e8185016120e5565b6001600160a01b03169085015261014061268a848201856128ca565b8684038388015261269c848284612566565b93505050506101606126b0818501856128ca565b868403838801526126c2848284612566565b979650505050505050565b8183823760009101908152919050565b6020808252825182820181905260009190848201906040850190845b81811015612715578351835292840192918401916001016126f9565b50909695505050505050565b604081526000612735604083018587612566565b9050826020830152949350505050565b604081526000612758604083018561258f565b90508260208301529392505050565b61277084612b43565b838152606060208201526000612789606083018561258f565b9050826040830152949350505050565b60a0815260006127ac60a08301886125bb565b82810360208401526127be818861258f565b9150508460408301528360608301526127d683612b43565b8260808301529695505050505050565b60408152600061275860408301856125bb565b8381526001600160a01b03831660208201526060604082018190526000906107e39083018461258f565b8281526040602082015260006123d1604083018461258f565b6000808335601e1984360301811261285357600080fd5b8301803591506001600160401b0382111561286d57600080fd5b602001915036819003821315610d6957600080fd5b6000823561017e1983360301811261289957600080fd5b9190910192915050565b60006001600160401b038211156128bc576128bc612a88565b50601f01601f191660200190565b6000808335601e198436030181126128e157600080fd5b83016020810192503590506001600160401b0381111561290057600080fd5b803603831315610d6957600080fd5b6000821982111561292257612922612a46565b500190565b600063ffffffff80831681851680830382111561294657612946612a46565b01949350505050565b60006001600160601b0380831681851680830382111561294657612946612a46565b600081600019048311821515161561298b5761298b612a46565b500290565b6000828210156129a2576129a2612a46565b500390565b60006001600160601b03838116908316818110156129c7576129c7612a46565b039392505050565b60005b838110156129ea5781810151838201526020016129d2565b838111156129f9576000848401525b50505050565b601f8201601f191681016001600160401b0381118282101715612a2457612a24612a88565b6040525050565b6000600019821415612a3f57612a3f612a46565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115612ab75760046000803e5060005160e01c5b90565b600060443d1015612ac85790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715612af757505050505090565b8285019150815181811115612b0f5750505050505090565b843d8701016020828501011115612b295750505050505090565b612b38602082860101876129ff565b509095945050505050565b6003811061209a57634e487b7160e01b600052602160045260246000fd5b6001600160a01b038116811461209a57600080fdfea26469706673582212207d15049d6b9c7e811e26d8092a0a93a7d0ccb320de507c9e54141a4480435a1c64736f6c63430008070033",
+ "deployedBytecode": "0x6080604052600436106101235760003560e01c8063af2ed7d7116100a0578063c345315311610064578063c345315314610446578063dbbabd6a1461053c578063e7c350e31461055c578063f20751eb146105a5578063f3737f19146105c657600080fd5b8063af2ed7d71461033a578063bb9fe6bf1461035a578063bf55512e1461036f578063c23a5cea1461038f578063c31e4354146103af57600080fd5b80632815c17b116100e75780632815c17b146102755780634a58db1914610295578063643407ce1461029d578063739b8950146102df578063828190131461030c57600080fd5b80630396cb601461012f5780630bfb68471461014457806316934fc4146101955780631c112a44146102255780631fa75c861461025557600080fd5b3661012a57005b600080fd5b61014261013d366004612540565b6105d9565b005b34801561015057600080fd5b506101787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a157600080fd5b506101ee6101b0366004612161565b6000602081905290815260409020546001600160601b038082169163ffffffff600160601b8204811692600160801b83041691600160e01b90041684565b604080516001600160601b03958616815263ffffffff9485166020820152949092169184019190915216606082015260800161018c565b34801561023157600080fd5b506102456102403660046121c7565b610764565b604051901515815260200161018c565b34801561026157600080fd5b5061024561027036600461219b565b6107ec565b34801561028157600080fd5b5061014261029036600461223d565b610826565b610142610c24565b3480156102a957600080fd5b506102d17f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161018c565b3480156102eb57600080fd5b506102ff6102fa3660046121fc565b610c30565b60405161018c91906126dd565b34801561031857600080fd5b5061032c6103273660046124e3565b610d09565b60405161018c929190612745565b34801561034657600080fd5b506102d161035536600461242a565b610d70565b34801561036657600080fd5b50610142610ee2565b34801561037b57600080fd5b506102d161038a36600461239d565b611055565b34801561039b57600080fd5b506101426103aa366004612161565b6110e0565b3480156103bb57600080fd5b506101786103ca366004612314565b8151602092830120604080516001600160f81b0319818601527f000000000000000000000000000000000000000000000000000000000000000060601b6bffffffffffffffffffffffff191660218201526035810193909352605580840192909252805180840390920182526075909201909152805191012090565b34801561045257600080fd5b506104eb610461366004612161565b604080516080810182526000808252602082018190529181018290526060810191909152506001600160a01b031660009081526020818152604091829020825160808101845290546001600160601b03808216835263ffffffff600160601b8304811694840194909452600160801b82041693820193909352600160e01b90920416606082015290565b60405161018c919060006080820190506001600160601b03808451168352602084015163ffffffff808216602086015282604087015116604086015280606087015116606086015250505092915050565b34801561054857600080fd5b506101426105573660046123d9565b611311565b34801561056857600080fd5b506105907f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161018c565b3480156105b157600080fd5b506102456105c0366004612161565b3f151590565b6101426105d4366004612161565b61142b565b3360009081526020819052604090205463ffffffff600160601b9091048116908216101561064e5760405162461bcd60e51b815260206004820152601e60248201527f63616e6e6f7420646563726561736520756e7374616b6520626c6f636b73000060448201526064015b60405180910390fd5b336000908152602081905260408120546001600160601b03600160801b820481169161067c9134911661290f565b610686919061290f565b604080516080810182526001600160601b0383811680835263ffffffff878116602080860182815260008789018181526060890182815233808452838652928b902099518a54945192519151908a166001600160801b031990951694909417600160601b92881692909202919091176001600160801b0316600160801b91909816026001600160e01b031696909617600160e01b91909416029290921790945584519182528101929092529293507f270d6dd254edd1d985c81cf7861b8f28fb06b6d719df04d90464034d4341244091015b60405180910390a25050565b6001600160a01b038316600090815260208181526040808320815160808101835290546001600160601b0380821680845263ffffffff600160601b8404811696850196909652600160801b830490911693830193909352600160e01b9004909216606083015284118015906107e3575082816020015163ffffffff1610155b95945050505050565b600061081f83837f000000000000000000000000000000000000000000000000000000000000000063ffffffff16610764565b9392505050565b816000816001600160401b0381111561084157610841612a88565b60405190808252806020026020018201604052801561086a578160200160208202803683370190505b5090506000826001600160401b0381111561088757610887612a88565b6040519080825280602002602001820160405280156108b0578160200160208202803683370190505b5090506000836001600160401b038111156108cd576108cd612a88565b6040519080825280602002602001820160405280156108f6578160200160208202803683370190505b5090506000846001600160401b0381111561091357610913612a88565b60405190808252806020026020018201604052801561093c578160200160208202803683370190505b50905060005b85811015610a735760005a9050368a8a8481811061096257610962612a72565b90506020028101906109749190612882565b9050606060006109848584611483565b89888151811061099657610996612a72565b602002602001018989815181106109af576109af612a72565b602002602001018296508360028111156109cb576109cb612a5c565b60028111156109dc576109dc612a5c565b81525083815250505050819050808886815181106109fc576109fc612a72565b6020026020010181815250507f00000000000000000000000000000000000000000000000000000000000000005a610a349086612990565b610a3e919061290f565b898681518110610a5057610a50612a72565b602002602001018181525050505050508080610a6b90612a2b565b915050610942565b506000805b88811015610c0e5760005a9050368b8b84818110610a9857610a98612a72565b9050602002810190610aaa9190612882565b90506000878481518110610ac057610ac0612a72565b60200260200101519050606081905060008a8681518110610ae357610ae3612a72565b602002602001015190506000898781518110610b0157610b01612a72565b602002602001015190506000898881518110610b1f57610b1f612a72565b60200260200101519050306001600160a01b031663af2ed7d787868686866040518663ffffffff1660e01b8152600401610b5d959493929190612799565b602060405180830381600087803b158015610b7757600080fd5b505af1925050508015610ba7575060408051601f3d908101601f19168201909252610ba491810190612527565b60015b610be6576000835a610bb9908a612990565b610bc3919061290f565b9050610bd460028887848787611589565b610bde908b61290f565b995050610bf4565b610bf0818b61290f565b9950505b505050505050508080610c0690612a2b565b915050610a78565b50610c19878261182d565b505050505050505050565b610c2e60006105d9565b565b6060816001600160401b03811115610c4a57610c4a612a88565b604051908082528060200260200182016040528015610c73578160200160208202803683370190505b50905060005b82811015610d0257600080858584818110610c9657610c96612a72565b9050602002016020810190610cab9190612161565b6001600160a01b0316815260208101919091526040016000205482516001600160601b0390911690839083908110610ce557610ce5612a72565b602090810291909101015280610cfa81612a2b565b915050610c79565b5092915050565b60606000806000610d1986611868565b90925090506000816002811115610d3257610d32612a5c565b14610d555760006040518060200160405280600081525090935093505050610d69565b610d6260008784886118cf565b9350935050505b9250929050565b6000805a9050333014610d8257600080fd5b600080610d9260608b018b61283c565b90501115610e74576000808a356001600160a01b031660808c0135610dba60608e018e61283c565b604051610dc89291906126cd565b60006040518083038160008787f1925050503d8060008114610e06576040519150601f19603f3d011682016040523d82523d6000602084013e610e0b565b606091505b509150915081158015610e1f575060008151115b15610e71578a356001600160a01b03167fbe4889eb241fb33bc0e9873f6e442f4c5dc653a55e7ad8bca2f001c9b3d818fb8c6020013583604051610e64929190612823565b60405180910390a2600192505b50505b6000865a610e829085612990565b610e8c919061290f565b9050610ed4828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508792508c91508b9050611589565b9a9950505050505050505050565b3360009081526020819052604090208054600160e01b900463ffffffff1615610f3f5760405162461bcd60e51b815260206004820152600f60248201526e616c72656164792070656e64696e6760881b6044820152606401610645565b80546001600160601b031615801590610f6557508054600160601b900463ffffffff1615155b610fa65760405162461bcd60e51b81526020600482015260126024820152716e6f207374616b6520746f20756e6c6f636b60701b6044820152606401610645565b8054600090610fc290600160601b900463ffffffff1643612927565b82546001600160801b0381166bffffffffffffffffffffffff60801b19600160e01b63ffffffff8516908102918216929092176001600160601b039384169190931617600160801b02919091176bffffffffffffffffffffffff1916845560405190815290915033907fab3a43860ac8cdb29929ba1a1f556b4decf9617f4811c190010e1672e55839b190602001610758565b600033156110ba5760405162461bcd60e51b815260206004820152602c60248201527f6d7573742062652063616c6c6564206f66662d636861696e207769746820667260448201526b37b69ebd32b93796b0b2323960a11b6064820152608401610645565b6000806110c684611868565b915091506110d76000858484611aab565b50949350505050565b3360009081526020818152604091829020825160808101845290546001600160601b03808216835263ffffffff600160601b83048116948401859052600160801b830490911694830194909452600160e01b90049092166060830152156111e457600081604001516001600160601b0316116111925760405162461bcd60e51b81526020600482015260116024820152706e6f20756e6c6f636b6564207374616b6560781b6044820152606401610645565b43816060015163ffffffff1611156111e45760405162461bcd60e51b81526020600482015260156024820152745769746864726177616c206973206e6f742064756560581b6044820152606401610645565b805160408201516000916111f79161294f565b60408051608081018252600080825260208681015163ffffffff9081168285019081528486018481526060860185815233865293859052868520955186549251915194518416600160e01b026001600160e01b036001600160601b03968716600160801b02166001600160801b0393909516600160601b026001600160801b031990941691861691909117929092171691909117179092559151921692506001600160a01b0385169183156108fc0291849190818181858888f193505050501580156112c7573d6000803e3d6000fd5b50604080516001600160a01b03851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a2505050565b60005a90506000806000611326600087611483565b92509250925060007f00000000000000000000000000000000000000000000000000000000000000005a61135a9087612990565b611364919061290f565b60405163af2ed7d760e01b8152909150600090309063af2ed7d790611395908b90879087908b908b90600401612799565b602060405180830381600087803b1580156113af57600080fd5b505af19250505080156113df575060408051601f3d908101601f191682019092526113dc91810190612527565b60015b611414576000825a6113f19089612990565b6113fb919061290f565b905061140c60028a86848a8a611589565b915050611417565b90505b611421878261182d565b5050505050505050565b6001600160a01b0381166000908152602081905260408120805434929061145c9084906001600160601b031661294f565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555050565b600080606060005a905060008061149987611868565b955090506114a988888388611aab565b965091506000808660028111156114c2576114c2612a5c565b14156114de576114d4898984866118cf565b90955090506114f1565b6040518060200160405280600081525094505b60005a6114fe9086612990565b9050808960a00135101561157d578961151f6101408b016101208c01612161565b60405162fa072b60e01b815260048101929092526001600160a01b0316602482015260606044820152601e60648201527f55736564206d6f7265207468616e20766572696669636174696f6e4761730000608482015260a401610645565b50505050509250925092565b6000805a9050600061159a88611d77565b90506115a68187612971565b925060008460028111156115bc576115bc612a5c565b14611663578285101561161c5760405162461bcd60e51b815260206004820152602260248201527f77616c6c65742070726566756e642062656c6f772061637475616c476173436f6044820152611cdd60f21b6064820152608401610645565b60006116288487612990565b9050600185600281111561163e5761163e612a5c565b14156116535761164e8982611d94565b61165d565b61165d8982611dee565b50611801565b86511561176f5761167c61014089016101208a01612161565b6001600160a01b031663a9a234098a89866040518463ffffffff1660e01b81526004016116ab93929190612767565b600060405180830381600087803b1580156116c557600080fd5b505af19250505080156116d6575060015b61176f573d808015611704576040519150601f19603f3d011682016040523d82523d6000602084013e611709565b606091505b5061171c6101408a016101208b01612161565b6001600160a01b031689356001600160a01b03167f45197bfe91c32368fd75a4fcab42a1eff7699e79df0e171a343537be7657efb68b6020013584604051611765929190612823565b60405180910390a3505b5a61177a9083612990565b611784908761290f565b95506117908187612971565b9250826000806117a86101408c016101208d01612161565b6001600160a01b031681526020810191909152604001600090812080549091906117dc9084906001600160601b03166129a7565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b61182188848360008d600281111561181b5761181b612a5c565b14611e1b565b50509695505050505050565b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611863573d6000803e3d6000fd5b505050565b600080611895837f0000000000000000000000000000000000000000000000000000000000000000611e97565b91506118a083611ec6565b156118ad57506000915091565b6118ba8335836000610764565b156118c757506001915091565b506002915091565b60606000805a90506118e18686611eec565b61194957866118f861014088016101208901612161565b60405162fa072b60e01b815260048101929092526001600160a01b0316602482015260606044820152601060648201526f6e6f7420656e6f756768207374616b6560801b608482015260a401610645565b60006119598560a0890135612990565b905061196d61014088016101208901612161565b6001600160a01b03166380fd44d58289896040518463ffffffff1660e01b815260040161199b9291906127e6565b60006040518083038187803b1580156119b357600080fd5b5086fa935050505080156119e957506040513d6000823e601f3d908101601f191682016040526119e69190810190612293565b60015b611a91576119f5612a9e565b806308c379a01415611a445750611a0a612aba565b80611a155750611a46565b88611a286101408a016101208b01612161565b8260405162fa072b60e01b8152600401610645939291906127f9565b505b87611a5961014089016101208a01612161565b60405162fa072b60e01b815260048101929092526001600160a01b031660248201526060604482015260006064820152608401610645565b93505a611a9e9083612990565b9250505094509492505050565b60008060005a9050611abc86611f15565b4760006002866002811115611ad357611ad3612a5c565b1415611ae0575085611b04565b6001866002811115611af457611af4612a5c565b1415611b0457611b04888861209d565b6040516307dfd9cf60e51b81526001600160a01b038935169063fbfb39e09060a08b013590611b39908c9086906004016127e6565b600060405180830381600088803b158015611b5357600080fd5b5087f193505050508015611b65575060015b611be257611b71612a9e565b806308c379a01415611bb05750611b86612aba565b80611b915750611bb2565b8960008260405162fa072b60e01b8152600401610645939291906127f9565b505b60405162fa072b60e01b8152600481018a9052600060248201819052606060448301526064820152608401610645565b6000611bee8347612990565b90506002876002811115611c0457611c04612a5c565b1415611c705781811015611c685760405162fa072b60e01b8152600481018b90526000602482015260606044820152601960648201527f77616c6c6574206469646e2774207061792070726566756e6400000000000000608482015260a401610645565b809450611d5d565b6001876002811115611c8457611c84612a5c565b1415611cfd578015611cf55760405162fa072b60e01b8152600481018b90526000602482015260606044820152602660648201527f7573696e672077616c6c6574207374616b65206275742077616c6c65742070616084820152650d2c840cae8d60d31b60a482015260c401610645565b879450611d5d565b8015611d595760405162fa072b60e01b8152600481018b90526000602482015260606044820152601d60648201527f686173207061796d6173746572206275742077616c6c65742070616964000000608482015260a401610645565b8794505b5a611d689085612990565b95505050505094509492505050565b6000611d8e8260e0013548846101000135016120cf565b92915050565b6001600160a01b0382351660009081526020819052604081208054839290611dc69084906001600160601b031661294f565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050565b6040516000906001600160a01b038435169083156108fc0290849084818181858888f15050505050505050565b611e2d61014085016101208601612161565b6001600160a01b03168435604080516020808901358252810187905290810185905283151560608201526001600160a01b0391909116907fc27a60e61c14607957b41fa2dad696de47b2d80e390d0eaaf1514c0cd20342939060800160405180910390a350505050565b6000611ea283611d77565b611ebc83608086013560a08701350160c08701350161290f565b61081f9190612971565b600080611edb61014084016101208501612161565b6001600160a01b0316141592915050565b600061081f611f0361014085016101208601612161565b61027084670de0b6b3a764000061290f565b611f22604082018261283c565b15905061209a5760006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016634af63f02611f67604085018561283c565b6040516001600160e01b031960e085901b168152611f8f929190602088013590600401612721565b602060405180830381600087803b158015611fa957600080fd5b505af1158015611fbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe1919061217e565b90506001600160a01b03811661202a5760405162461bcd60e51b815260206004820152600e60248201526d18dc99585d194c8819985a5b195960921b6044820152606401610645565b81356001600160a01b0316816001600160a01b0316146120985760405162461bcd60e51b8152602060048201526024808201527f73656e64657220646f65736e2774206d617463682063726561746532206164646044820152637265737360e01b6064820152608401610645565b505b50565b6001600160a01b0382351660009081526020819052604081208054839290611dc69084906001600160601b03166129a7565b60008183106120de578161081f565b5090919050565b80356120f081612b61565b919050565b60008083601f84011261210757600080fd5b5081356001600160401b0381111561211e57600080fd5b6020830191508360208260051b8501011115610d6957600080fd5b8035600381106120f057600080fd5b6000610180828403121561215b57600080fd5b50919050565b60006020828403121561217357600080fd5b813561081f81612b61565b60006020828403121561219057600080fd5b815161081f81612b61565b600080604083850312156121ae57600080fd5b82356121b981612b61565b946020939093013593505050565b6000806000606084860312156121dc57600080fd5b83356121e781612b61565b95602085013595506040909401359392505050565b6000806020838503121561220f57600080fd5b82356001600160401b0381111561222557600080fd5b612231858286016120f5565b90969095509350505050565b60008060006040848603121561225257600080fd5b83356001600160401b0381111561226857600080fd5b612274868287016120f5565b909450925050602084013561228881612b61565b809150509250925092565b6000602082840312156122a557600080fd5b81516001600160401b038111156122bb57600080fd5b8201601f810184136122cc57600080fd5b80516122d7816128a3565b6040516122e482826129ff565b8281528660208486010111156122f957600080fd5b61230a8360208301602087016129cf565b9695505050505050565b6000806040838503121561232757600080fd5b82356001600160401b0381111561233d57600080fd5b8301601f8101851361234e57600080fd5b8035612359816128a3565b60405161236682826129ff565b82815287602084860101111561237b57600080fd5b8260208501602083013760006020938201840152979590910135955050505050565b6000602082840312156123af57600080fd5b81356001600160401b038111156123c557600080fd5b6123d184828501612148565b949350505050565b600080604083850312156123ec57600080fd5b82356001600160401b0381111561240257600080fd5b61240e85828601612148565b925050602083013561241f81612b61565b809150509250929050565b60008060008060008060a0878903121561244357600080fd5b86356001600160401b038082111561245a57600080fd5b6124668a838b01612148565b9750602089013591508082111561247c57600080fd5b818901915089601f83011261249057600080fd5b81358181111561249f57600080fd5b8a60208285010111156124b157600080fd5b60208301975080965050505060408701359250606087013591506124d760808801612139565b90509295509295509295565b600080604083850312156124f657600080fd5b82356001600160401b0381111561250c57600080fd5b61251885828601612148565b95602094909401359450505050565b60006020828403121561253957600080fd5b5051919050565b60006020828403121561255257600080fd5b813563ffffffff8116811461081f57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600081518084526125a78160208601602086016129cf565b601f01601f19169290920160200192915050565b60006101806125da846125cd856120e5565b6001600160a01b03169052565b602083013560208501526125f160408401846128ca565b8260408701526126048387018284612566565b9250505061261560608401846128ca565b8583036060870152612628838284612566565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e085015261010080840135818601525061012061266e8185016120e5565b6001600160a01b03169085015261014061268a848201856128ca565b8684038388015261269c848284612566565b93505050506101606126b0818501856128ca565b868403838801526126c2848284612566565b979650505050505050565b8183823760009101908152919050565b6020808252825182820181905260009190848201906040850190845b81811015612715578351835292840192918401916001016126f9565b50909695505050505050565b604081526000612735604083018587612566565b9050826020830152949350505050565b604081526000612758604083018561258f565b90508260208301529392505050565b61277084612b43565b838152606060208201526000612789606083018561258f565b9050826040830152949350505050565b60a0815260006127ac60a08301886125bb565b82810360208401526127be818861258f565b9150508460408301528360608301526127d683612b43565b8260808301529695505050505050565b60408152600061275860408301856125bb565b8381526001600160a01b03831660208201526060604082018190526000906107e39083018461258f565b8281526040602082015260006123d1604083018461258f565b6000808335601e1984360301811261285357600080fd5b8301803591506001600160401b0382111561286d57600080fd5b602001915036819003821315610d6957600080fd5b6000823561017e1983360301811261289957600080fd5b9190910192915050565b60006001600160401b038211156128bc576128bc612a88565b50601f01601f191660200190565b6000808335601e198436030181126128e157600080fd5b83016020810192503590506001600160401b0381111561290057600080fd5b803603831315610d6957600080fd5b6000821982111561292257612922612a46565b500190565b600063ffffffff80831681851680830382111561294657612946612a46565b01949350505050565b60006001600160601b0380831681851680830382111561294657612946612a46565b600081600019048311821515161561298b5761298b612a46565b500290565b6000828210156129a2576129a2612a46565b500390565b60006001600160601b03838116908316818110156129c7576129c7612a46565b039392505050565b60005b838110156129ea5781810151838201526020016129d2565b838111156129f9576000848401525b50505050565b601f8201601f191681016001600160401b0381118282101715612a2457612a24612a88565b6040525050565b6000600019821415612a3f57612a3f612a46565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060033d1115612ab75760046000803e5060005160e01c5b90565b600060443d1015612ac85790565b6040516003193d81016004833e81513d6001600160401b038160248401118184111715612af757505050505090565b8285019150815181811115612b0f5750505050505090565b843d8701016020828501011115612b295750505050505090565b612b38602082860101876129ff565b509095945050505050565b6003811061209a57634e487b7160e01b600052602160045260246000fd5b6001600160a01b038116811461209a57600080fdfea26469706673582212207d15049d6b9c7e811e26d8092a0a93a7d0ccb320de507c9e54141a4480435a1c64736f6c63430008070033",
+ "devdoc": {
+ "kind": "dev",
+ "methods": {
+ "handleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),address)": {
+ "params": {
+ "op": "the operation to execute",
+ "redeemer": "the contract to redeem the fee"
+ }
+ },
+ "simulatePaymasterValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),uint256)": {
+ "params": {
+ "gasUsedByPayForSelfOp": "- the gas returned by simulateWalletValidation, as these 2 calls should share the same userOp.validationGas quota. The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the paymaster's data",
+ "userOp": "the user operation to validate."
+ }
+ },
+ "simulateWalletValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes))": {
+ "returns": {
+ "gasUsedByPayForSelfOp": "- gas used by the validation, to pass into simulatePaymasterValidation. The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the wallet's data"
+ }
+ }
+ },
+ "version": 1
+ },
+ "userdoc": {
+ "events": {
+ "StakeUnlocking(address,uint256)": {
+ "notice": "Emitted once a stake is scheduled for withdrawal"
+ }
+ },
+ "kind": "user",
+ "methods": {
+ "addDeposit()": {
+ "notice": "add a deposit (just like stake, but with lock=0 cancel any pending unlock"
+ },
+ "addStake(uint32)": {
+ "notice": "add stake value for this paymaster. cancel any pending unlock"
+ },
+ "handleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),address)": {
+ "notice": "Execute the given UserOperation."
+ },
+ "simulatePaymasterValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes),uint256)": {
+ "notice": "Simulate a call to paymaster.verifyPaymasterUserOp do nothing if has no paymaster."
+ },
+ "simulateWalletValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,address,bytes,bytes))": {
+ "notice": "Simulate a call for wallet.verifyUserOp. Call must not revert."
+ },
+ "stakes(address)": {
+ "notice": "maps relay managers to their stakes"
+ },
+ "unstakeDelayBlocks()": {
+ "notice": "minimum number of blocks to after 'unlock' before amount can be withdrawn."
+ }
+ },
+ "version": 1
+ },
+ "storageLayout": {
+ "storage": [
+ {
+ "astId": 2325,
+ "contract": "contracts/EntryPoint.sol:EntryPoint",
+ "label": "stakes",
+ "offset": 0,
+ "slot": "0",
+ "type": "t_mapping(t_address,t_struct(StakeInfo)2319_storage)"
+ }
+ ],
+ "types": {
+ "t_address": {
+ "encoding": "inplace",
+ "label": "address",
+ "numberOfBytes": "20"
+ },
+ "t_mapping(t_address,t_struct(StakeInfo)2319_storage)": {
+ "encoding": "mapping",
+ "key": "t_address",
+ "label": "mapping(address => struct StakeManager.StakeInfo)",
+ "numberOfBytes": "32",
+ "value": "t_struct(StakeInfo)2319_storage"
+ },
+ "t_struct(StakeInfo)2319_storage": {
+ "encoding": "inplace",
+ "label": "struct StakeManager.StakeInfo",
+ "members": [
+ {
+ "astId": 2312,
+ "contract": "contracts/EntryPoint.sol:EntryPoint",
+ "label": "stake",
+ "offset": 0,
+ "slot": "0",
+ "type": "t_uint96"
+ },
+ {
+ "astId": 2314,
+ "contract": "contracts/EntryPoint.sol:EntryPoint",
+ "label": "unstakeDelayBlocks",
+ "offset": 12,
+ "slot": "0",
+ "type": "t_uint32"
+ },
+ {
+ "astId": 2316,
+ "contract": "contracts/EntryPoint.sol:EntryPoint",
+ "label": "withdrawStake",
+ "offset": 16,
+ "slot": "0",
+ "type": "t_uint96"
+ },
+ {
+ "astId": 2318,
+ "contract": "contracts/EntryPoint.sol:EntryPoint",
+ "label": "withdrawBlock",
+ "offset": 28,
+ "slot": "0",
+ "type": "t_uint32"
+ }
+ ],
+ "numberOfBytes": "32"
+ },
+ "t_uint32": {
+ "encoding": "inplace",
+ "label": "uint32",
+ "numberOfBytes": "4"
+ },
+ "t_uint96": {
+ "encoding": "inplace",
+ "label": "uint96",
+ "numberOfBytes": "12"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/SimpleWallet.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/SimpleWallet.json
new file mode 100644
index 000000000..6b14b548f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/SimpleWallet.json
@@ -0,0 +1,338 @@
+{
+ "address": "0x16d53bCF7d1614D0fF81559abB94bfBC7d3B84D9",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "contract EntryPoint",
+ "name": "_entryPoint",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "_owner",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "contract EntryPoint",
+ "name": "oldEntryPoint",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "contract EntryPoint",
+ "name": "newEntryPoint",
+ "type": "address"
+ }
+ ],
+ "name": "EntryPointChanged",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "addDeposit",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "entryPoint",
+ "outputs": [
+ {
+ "internalType": "contract EntryPoint",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "func",
+ "type": "bytes"
+ }
+ ],
+ "name": "exec",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "value",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "func",
+ "type": "bytes"
+ }
+ ],
+ "name": "execFromEntryPoint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "nonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "dest",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "transfer",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "contract EntryPoint",
+ "name": "_entryPoint",
+ "type": "address"
+ }
+ ],
+ "name": "updateEntryPoint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "uint256",
+ "name": "requiredPrefund",
+ "type": "uint256"
+ }
+ ],
+ "name": "verifyUserOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawDeposit",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [
+ "0xF63621e54F16eC6e4A732e44EaA7708935f259eF",
+ "0xd21934eD8eAf27a67f0A70042Af50A1D6d195E81"
+ ],
+ "solcInputHash": "9255faacf3ae4e81db1326413027bfa0",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract EntryPoint\",\"name\":\"_entryPoint\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract EntryPoint\",\"name\":\"oldEntryPoint\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract EntryPoint\",\"name\":\"newEntryPoint\",\"type\":\"address\"}],\"name\":\"EntryPointChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"addDeposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"entryPoint\",\"outputs\":[{\"internalType\":\"contract EntryPoint\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dest\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"func\",\"type\":\"bytes\"}],\"name\":\"exec\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dest\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"func\",\"type\":\"bytes\"}],\"name\":\"execFromEntryPoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"dest\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract EntryPoint\",\"name\":\"_entryPoint\",\"type\":\"address\"}],\"name\":\"updateEntryPoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"requiredPrefund\",\"type\":\"uint256\"}],\"name\":\"verifyUserOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/samples/SimpleWallet.sol\":\"SimpleWallet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/EntryPoint.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./StakeManager.sol\\\";\\nimport \\\"./UserOperation.sol\\\";\\nimport \\\"./IWallet.sol\\\";\\nimport \\\"./IPaymaster.sol\\\";\\n\\ninterface ICreate2Deployer {\\n function deploy(bytes memory _initCode, bytes32 _salt) external returns (address);\\n}\\n\\ncontract EntryPoint is StakeManager {\\n\\n using UserOperationLib for UserOperation;\\n // paymaster locked stake\\n // (actual stake should be higher, to cover actual call cost)\\n uint256 constant PAYMASTER_STAKE = 1 ether;\\n\\n enum PaymentMode {\\n paymasterStake, // if paymaster is set, use paymaster's stake to pay.\\n walletStake, // wallet has enough stake to pay for request.\\n walletEth // wallet has no stake. paying with eth.\\n }\\n\\n uint public immutable perOpOverhead;\\n address public immutable create2factory;\\n\\n event UserOperationEvent(address indexed sender, address indexed paymaster, uint nonce, uint actualGasCost, uint actualGasPrice, bool success);\\n event UserOperationRevertReason(address indexed sender, uint nonce, bytes revertReason);\\n\\n event PaymasterPostOpFailed(address indexed sender, address indexed paymaster, uint nonce, bytes reason);\\n\\n //handleOps reverts with this error struct, to mark the offending op\\n // NOTE: if simulateOp passes successfully, there should be no reason for handleOps to fail on it.\\n // @param opIndex - index into the array of ops to the failed one (in simulateOp, this is always zero)\\n // @param paymaster - if paymaster.verifyPaymasterUserOp fails, this will be the paymaster's address. if verifyUserOp failed,\\n // this value will be zero (since it failed before accessing the paymaster)\\n // @param reason - revert reason\\n // only to aid troubleshooting of wallet/paymaster reverts\\n error FailedOp(uint opIndex, address paymaster, string reason);\\n\\n constructor(address _create2factory, uint _perOpOverhead, uint32 _unstakeDelayBlocks) StakeManager(_unstakeDelayBlocks) {\\n create2factory = _create2factory;\\n perOpOverhead = _perOpOverhead;\\n }\\n\\n receive() external payable {}\\n\\n /**\\n * Execute the given UserOperation.\\n * @param op the operation to execute\\n * @param redeemer the contract to redeem the fee\\n */\\n function handleOp(UserOperation calldata op, address payable redeemer) public {\\n\\n uint preGas = gasleft();\\n\\n (uint256 prefund, PaymentMode paymentMode, bytes memory context) = _validatePrepayment(0, op);\\n uint preOpGas = preGas - gasleft() + perOpOverhead;\\n\\n uint actualGasCost;\\n\\n try this.internalHandleOp(op, context, preOpGas, prefund, paymentMode) returns (uint _actualGasCost) {\\n actualGasCost = _actualGasCost;\\n } catch {\\n uint actualGas = preGas - gasleft() + preOpGas;\\n actualGasCost = handlePostOp(IPaymaster.PostOpMode.postOpReverted, op, context, actualGas, prefund, paymentMode);\\n }\\n\\n redeem(redeemer, actualGasCost);\\n }\\n\\n function redeem(address payable redeemer, uint amount) internal {\\n redeemer.transfer(amount);\\n }\\n\\n function handleOps(UserOperation[] calldata ops, address payable redeemer) public {\\n\\n uint opslen = ops.length;\\n uint256[] memory preOpGas = new uint256[](opslen);\\n bytes32[] memory contexts = new bytes32[](opslen);\\n uint256[] memory prefunds = new uint256[](opslen);\\n PaymentMode[] memory paymentModes = new PaymentMode[](opslen);\\n\\n for (uint i = 0; i < opslen; i++) {\\n uint preGas = gasleft();\\n UserOperation calldata op = ops[i];\\n\\n bytes memory context;\\n bytes32 contextOffset;\\n (prefunds[i], paymentModes[i], context) = _validatePrepayment(i, op);\\n assembly {contextOffset := context}\\n contexts[i] = contextOffset;\\n preOpGas[i] = preGas - gasleft() + perOpOverhead;\\n }\\n\\n uint collected = 0;\\n\\n for (uint i = 0; i < ops.length; i++) {\\n uint preGas = gasleft();\\n UserOperation calldata op = ops[i];\\n bytes32 contextOffset = contexts[i];\\n bytes memory context;\\n assembly {context := contextOffset}\\n uint preOpGasi = preOpGas[i];\\n uint prefundi = prefunds[i];\\n PaymentMode paymentModei = paymentModes[i];\\n\\n try this.internalHandleOp(op, context, preOpGasi, prefundi, paymentModei) returns (uint _actualGasCost) {\\n collected += _actualGasCost;\\n } catch {\\n uint actualGas = preGas - gasleft() + preOpGasi;\\n collected += handlePostOp(IPaymaster.PostOpMode.postOpReverted, op, context, actualGas, prefundi, paymentModei);\\n }\\n }\\n\\n redeem(redeemer, collected);\\n }\\n\\n function internalHandleOp(UserOperation calldata op, bytes calldata context, uint preOpGas, uint prefund, PaymentMode paymentMode) external returns (uint actualGasCost) {\\n uint preGas = gasleft();\\n require(msg.sender == address(this));\\n\\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\\n if (op.callData.length > 0) {\\n\\n (bool success,bytes memory result) = address(op.getSender()).call{gas : op.callGas}(op.callData);\\n if (!success && result.length > 0) {\\n emit UserOperationRevertReason(op.getSender(), op.nonce, result);\\n mode = IPaymaster.PostOpMode.opReverted;\\n }\\n }\\n\\n uint actualGas = preGas - gasleft() + preOpGas;\\n return handlePostOp(mode, op, context, actualGas, prefund, paymentMode);\\n }\\n\\n /**\\n * Simulate a call for wallet.verifyUserOp.\\n * Call must not revert.\\n * @return gasUsedByPayForSelfOp - gas used by the validation, to pass into simulatePaymasterValidation.\\n * The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the wallet's data\\n */\\n function simulateWalletValidation(UserOperation calldata userOp) external returns (uint gasUsedByPayForSelfOp){\\n require(msg.sender == address(0), \\\"must be called off-chain with from=zero-addr\\\");\\n (uint requiredPreFund, PaymentMode paymentMode) = getPaymentInfo(userOp);\\n (gasUsedByPayForSelfOp,) = _validateWalletPrepayment(0, userOp, requiredPreFund, paymentMode);\\n }\\n\\n function getPaymentInfo(UserOperation calldata userOp) internal view returns (uint requiredPrefund, PaymentMode paymentMode) {\\n requiredPrefund = userOp.requiredPreFund(perOpOverhead);\\n if (userOp.hasPaymaster()) {\\n paymentMode = PaymentMode.paymasterStake;\\n } else if (isStaked(userOp.getSender(), requiredPrefund, 0)) {\\n paymentMode = PaymentMode.walletStake;\\n } else {\\n paymentMode = PaymentMode.walletEth;\\n }\\n }\\n\\n /**\\n * Simulate a call to paymaster.verifyPaymasterUserOp\\n * do nothing if has no paymaster.\\n * @param userOp the user operation to validate.\\n * @param gasUsedByPayForSelfOp - the gas returned by simulateWalletValidation, as these 2 calls should share\\n * the same userOp.validationGas quota.\\n * The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the paymaster's data\\n */\\n function simulatePaymasterValidation(UserOperation calldata userOp, uint gasUsedByPayForSelfOp) external view returns (bytes memory context, uint gasUsedByPayForOp){\\n (uint requiredPreFund, PaymentMode paymentMode) = getPaymentInfo(userOp);\\n if (paymentMode != PaymentMode.paymasterStake) {\\n return (\\\"\\\", 0);\\n }\\n return _validatePaymasterPrepayment(0, userOp, requiredPreFund, gasUsedByPayForSelfOp);\\n }\\n\\n // get the sender address, or use \\\"create2\\\" to create it.\\n // note that the gas allocation for this creation is deterministic (by the size of callData),\\n // so it is not checked on-chain, and adds to the gas used by verifyUserOp\\n function _createSenderIfNeeded(UserOperation calldata op) internal {\\n if (op.initCode.length != 0) {\\n //its a create operation. run the create2\\n // note that we're still under the gas limit of validate, so probably\\n // this create2 creates a proxy account.\\n // appending signer makes the request unique, so no one else can make this request.\\n //nonce is meaningless during create, so we re-purpose it as salt\\n address sender1 = ICreate2Deployer(create2factory).deploy(op.initCode, bytes32(op.nonce));\\n require(sender1 != address(0), \\\"create2 failed\\\");\\n require(sender1 == op.getSender(), \\\"sender doesn't match create2 address\\\");\\n }\\n }\\n\\n //get counterfactual sender address.\\n // use the initCode and salt in the UserOperation tot create this sender contract\\n function getSenderAddress(bytes memory initCode, uint _salt) public view returns (address) {\\n bytes32 hash = keccak256(\\n abi.encodePacked(\\n bytes1(0xff),\\n address(create2factory),\\n _salt,\\n keccak256(initCode)\\n )\\n );\\n\\n // NOTE: cast last 20 bytes of hash to address\\n return address(uint160(uint256(hash)));\\n }\\n\\n //call wallet.verifyUserOp, and validate that it paid as needed.\\n // return actual value sent from wallet to \\\"this\\\"\\n function _validateWalletPrepayment(uint opIndex, UserOperation calldata op, uint requiredPrefund, PaymentMode paymentMode) internal returns (uint gasUsedByPayForSelfOp, uint prefund) {\\n uint preGas = gasleft();\\n _createSenderIfNeeded(op);\\n uint preBalance = address(this).balance;\\n uint requiredEthPrefund = 0;\\n if (paymentMode == PaymentMode.walletEth) {\\n requiredEthPrefund = requiredPrefund;\\n } else if (paymentMode == PaymentMode.walletStake) {\\n _prefundFromSender(op, requiredPrefund);\\n } else {\\n // paymaster pays in handlePostOp\\n }\\n try IWallet(op.getSender()).verifyUserOp{gas : op.verificationGas}(op, requiredEthPrefund) {\\n } catch Error(string memory revertReason) {\\n revert FailedOp(opIndex, address(0), revertReason);\\n } catch {\\n revert FailedOp(opIndex, address(0), \\\"\\\");\\n }\\n uint actualEthPrefund = address(this).balance - preBalance;\\n\\n if (paymentMode == PaymentMode.walletEth) {\\n if (actualEthPrefund < requiredEthPrefund) {\\n revert FailedOp(opIndex, address(0), \\\"wallet didn't pay prefund\\\");\\n }\\n prefund = actualEthPrefund;\\n } else if (paymentMode == PaymentMode.walletStake) {\\n if (actualEthPrefund != 0) {\\n revert FailedOp(opIndex, address(0), \\\"using wallet stake but wallet paid eth\\\");\\n }\\n prefund = requiredPrefund;\\n } else {\\n if (actualEthPrefund != 0) {\\n revert FailedOp(opIndex, address(0), \\\"has paymaster but wallet paid\\\");\\n }\\n prefund = requiredPrefund;\\n }\\n\\n gasUsedByPayForSelfOp = preGas - gasleft();\\n }\\n\\n //validate paymaster.verifyPaymasterUserOp\\n function _validatePaymasterPrepayment(uint opIndex, UserOperation calldata op, uint requiredPreFund, uint gasUsedByPayForSelfOp) internal view returns (bytes memory context, uint gasUsedByPayForOp) {\\n uint preGas = gasleft();\\n if (!isValidStake(op, requiredPreFund)) {\\n revert FailedOp(opIndex, op.paymaster, \\\"not enough stake\\\");\\n }\\n //no pre-pay from paymaster\\n uint gas = op.verificationGas - gasUsedByPayForSelfOp;\\n try IPaymaster(op.paymaster).verifyPaymasterUserOp{gas : gas}(op, requiredPreFund) returns (bytes memory _context){\\n context = _context;\\n } catch Error(string memory revertReason) {\\n revert FailedOp(opIndex, op.paymaster, revertReason);\\n } catch {\\n revert FailedOp(opIndex, op.paymaster, \\\"\\\");\\n }\\n gasUsedByPayForOp = preGas - gasleft();\\n }\\n\\n function _validatePrepayment(uint opIndex, UserOperation calldata userOp) private returns (uint prefund, PaymentMode paymentMode, bytes memory context){\\n\\n uint preGas = gasleft();\\n uint gasUsedByPayForSelfOp;\\n uint requiredPreFund;\\n (requiredPreFund, paymentMode) = getPaymentInfo(userOp);\\n\\n (gasUsedByPayForSelfOp, prefund) = _validateWalletPrepayment(opIndex, userOp, requiredPreFund, paymentMode);\\n\\n uint gasUsedByPayForOp = 0;\\n if (paymentMode == PaymentMode.paymasterStake) {\\n (context, gasUsedByPayForOp) = _validatePaymasterPrepayment(opIndex, userOp, requiredPreFund, gasUsedByPayForSelfOp);\\n } else {\\n context = \\\"\\\";\\n }\\n uint gasUsed = preGas - gasleft();\\n\\n if (userOp.verificationGas < gasUsed) {\\n revert FailedOp(opIndex, userOp.paymaster, \\\"Used more than verificationGas\\\");\\n }\\n }\\n\\n function getPaymastersStake(address[] calldata paymasters) external view returns (uint[] memory _stakes) {\\n _stakes = new uint[](paymasters.length);\\n for (uint i = 0; i < paymasters.length; i++) {\\n _stakes[i] = stakes[paymasters[i]].stake;\\n }\\n }\\n\\n function handlePostOp(IPaymaster.PostOpMode mode, UserOperation calldata op, bytes memory context, uint actualGas, uint prefund, PaymentMode paymentMode) private returns (uint actualGasCost) {\\n uint preGas = gasleft();\\n uint gasPrice = UserOperationLib.gasPrice(op);\\n actualGasCost = actualGas * gasPrice;\\n if (paymentMode != PaymentMode.paymasterStake) {\\n if (prefund < actualGasCost) {\\n revert (\\\"wallet prefund below actualGasCost\\\");\\n }\\n uint refund = prefund - actualGasCost;\\n if (paymentMode == PaymentMode.walletStake) {\\n _refundSenderStake(op, refund);\\n } else {\\n _refundSender(op, refund);\\n }\\n } else {\\n if (context.length > 0) {\\n //if paymaster.postOp reverts:\\n // - emit a message (just for sake of debugging of this poor paymaster)\\n // - paymaster still pays (from its stake)\\n try IPaymaster(op.paymaster).postOp(mode, context, actualGasCost) {}\\n catch (bytes memory errdata) {\\n emit PaymasterPostOpFailed(op.getSender(), op.paymaster, op.nonce, errdata);\\n }\\n }\\n //paymaster pays for full gas, including for postOp (and revert event)\\n actualGas += preGas - gasleft();\\n actualGasCost = actualGas * gasPrice;\\n //paymaster balance known to be high enough, and to be locked for this block\\n stakes[op.paymaster].stake -= uint96(actualGasCost);\\n }\\n _emitLog(op, actualGasCost, gasPrice, mode == IPaymaster.PostOpMode.opSucceeded);\\n }\\n\\n function _emitLog(UserOperation calldata op, uint actualGasCost, uint gasPrice, bool success) internal {\\n emit UserOperationEvent(op.getSender(), op.paymaster, op.nonce, actualGasCost, gasPrice, success);\\n }\\n\\n function _prefundFromSender(UserOperation calldata userOp, uint requiredPrefund) internal {\\n stakes[userOp.getSender()].stake -= uint96(requiredPrefund);\\n }\\n\\n function _refundSender(UserOperation calldata userOp, uint refund) internal {\\n //NOTE: deliberately ignoring revert: wallet should accept refund.\\n bool sendOk = payable(userOp.getSender()).send(refund);\\n (sendOk);\\n }\\n function _refundSenderStake(UserOperation calldata userOp, uint refund) internal {\\n stakes[userOp.getSender()].stake += uint96(refund);\\n }\\n\\n function isValidStake(UserOperation calldata userOp, uint requiredPreFund) internal view returns (bool) {\\n return isPaymasterStaked(userOp.paymaster, PAYMASTER_STAKE + requiredPreFund);\\n }\\n\\n function isPaymasterStaked(address paymaster, uint stake) public view returns (bool) {\\n return isStaked(paymaster, stake, unstakeDelayBlocks);\\n }\\n\\n function isContractDeployed(address addr) external view returns (bool) {\\n bytes32 hash;\\n assembly {\\n hash := extcodehash(addr)\\n }\\n return hash != bytes32(0);\\n }\\n}\\n\\n\",\"keccak256\":\"0x8b15a6fcb66f95fc079400ff2b38de805405ce6c23c4bbbc1bcd24bb6cabefb0\",\"license\":\"GPL-3.0\"},\"contracts/IPaymaster.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\ninterface IPaymaster {\\n\\n enum PostOpMode {\\n opSucceeded, // user op succeeded\\n opReverted, // user op reverted. still has to pay for gas.\\n postOpReverted //user op succeeded, but caused postOp to revert. Now its a 2nd call, after user's op was deliberately reverted.\\n }\\n // payment validation: check if paymaster agree to pay (using its stake)\\n // revert to reject this request.\\n // actual payment is done after postOp is called, by deducting actual call cost form the paymaster's stake.\\n // @param userOp the user operation\\n // @param maxcost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\\n // @returns context value to send to a postOp\\n // zero length to signify postOp is not required.\\n function verifyPaymasterUserOp(UserOperation calldata userOp, uint maxcost) external view returns (bytes memory context);\\n\\n // post-operation handler.\\n // @param mode\\n // opSucceeded - user operation succeeded.\\n // opReverted - user op reverted. still has to pay for gas.\\n // postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\\n // Now this is the 2nd call, after user's op was deliberately reverted.\\n // @param context - the context value returned by verifyPaymasterUserOp\\n // @param actualGasCost - actual gas used so far (without this postOp call).\\n function postOp(PostOpMode mode, bytes calldata context, uint actualGasCost) external;\\n}\\n\",\"keccak256\":\"0xef51907c5520d22e74cc7804b30634cdc6d2cbf2fe96b77d0b6785a53c4545a5\",\"license\":\"GPL-3.0\"},\"contracts/IWallet.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\ninterface IWallet {\\n\\n // validate user's signature and nonce\\n // @param requiredPrefund how much this wallet should pre-fund the transaction.\\n // @note that after execution, the excess is sent back to the wallet.\\n // @note if requiredPrefund is zero, the wallet MUST NOT send anything (the paymaster pays)\\n function verifyUserOp(UserOperation calldata userOp, uint requiredPrefund) external;\\n}\\n\",\"keccak256\":\"0x29f98a4e6033cd10007dcc9b569fda950413cc91d8560a67f20a35e8185c9228\",\"license\":\"GPL-3.0\"},\"contracts/StakeManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-only\\npragma solidity ^0.8;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\ncontract StakeManager {\\n\\n /// minimum number of blocks to after 'unlock' before amount can be withdrawn.\\n uint32 immutable public unstakeDelayBlocks;\\n\\n constructor(uint32 _unstakeDelayBlocks) {\\n unstakeDelayBlocks = _unstakeDelayBlocks;\\n }\\n\\n event StakeAdded(\\n address indexed paymaster,\\n uint256 totalStake,\\n uint256 unstakeDelayBlocks\\n );\\n\\n /// Emitted once a stake is scheduled for withdrawal\\n event StakeUnlocking(\\n address indexed paymaster,\\n uint256 withdrawBlock\\n );\\n\\n event StakeWithdrawn(\\n address indexed paymaster,\\n address withdrawAddress,\\n uint256 amount\\n );\\n\\n /// @param stake - amount of ether staked for this paymaster\\n /// @param withdrawStake - once 'unlocked' the value is no longer staked.\\n /// @param withdrawBlock - first block number 'withdraw' will be callable, or zero if the unlock has not been called\\n struct StakeInfo {\\n uint96 stake;\\n uint32 unstakeDelayBlocks;\\n uint96 withdrawStake;\\n uint32 withdrawBlock;\\n }\\n\\n /// maps relay managers to their stakes\\n mapping(address => StakeInfo) public stakes;\\n\\n function getStakeInfo(address paymaster) external view returns (StakeInfo memory stakeInfo) {\\n return stakes[paymaster];\\n }\\n\\n /**\\n * add a deposit (just like stake, but with lock=0\\n * cancel any pending unlock\\n */\\n function addDeposit() external payable {\\n addStake(0);\\n }\\n\\n //add deposit to another account (doesn't change lock status)\\n function addDepositTo(address target) external payable {\\n stakes[target].stake += uint96(msg.value);\\n }\\n\\n /**\\n * add stake value for this paymaster.\\n * cancel any pending unlock\\n */\\n function addStake(uint32 _unstakeDelayBlocks) public payable {\\n require(_unstakeDelayBlocks >= stakes[msg.sender].unstakeDelayBlocks, \\\"cannot decrease unstake blocks\\\");\\n uint96 stake = uint96(stakes[msg.sender].stake + msg.value + stakes[msg.sender].withdrawStake);\\n stakes[msg.sender] = StakeInfo(\\n stake,\\n _unstakeDelayBlocks,\\n 0,\\n 0);\\n emit StakeAdded(msg.sender, stake, _unstakeDelayBlocks);\\n }\\n\\n function unlockStake() external {\\n StakeInfo storage info = stakes[msg.sender];\\n require(info.withdrawBlock == 0, \\\"already pending\\\");\\n require(info.stake != 0 && info.unstakeDelayBlocks != 0, \\\"no stake to unlock\\\");\\n uint32 withdrawBlock = uint32(block.number) + info.unstakeDelayBlocks;\\n info.withdrawBlock = withdrawBlock;\\n info.withdrawStake = info.stake;\\n info.stake = 0;\\n emit StakeUnlocking(msg.sender, withdrawBlock);\\n }\\n\\n function withdrawStake(address payable withdrawAddress) external {\\n StakeInfo memory info = stakes[msg.sender];\\n if (info.unstakeDelayBlocks != 0) {\\n require(info.withdrawStake > 0, \\\"no unlocked stake\\\");\\n require(info.withdrawBlock <= block.number, \\\"Withdrawal is not due\\\");\\n }\\n uint256 amount = info.withdrawStake + info.stake;\\n stakes[msg.sender] = StakeInfo(0, info.unstakeDelayBlocks, 0, 0);\\n withdrawAddress.transfer(amount);\\n emit StakeWithdrawn(msg.sender, withdrawAddress, amount);\\n }\\n\\n function isStaked(address paymaster, uint requiredStake, uint requiredDelayBlocks) public view returns (bool) {\\n StakeInfo memory stakeInfo = stakes[paymaster];\\n return stakeInfo.stake >= requiredStake && stakeInfo.unstakeDelayBlocks >= requiredDelayBlocks;\\n }\\n}\\n\",\"keccak256\":\"0x238f903aceaaa89fd289d99c16ff660b6f911837f50ccf3fc3bb94653024b1aa\",\"license\":\"GPL-3.0-only\"},\"contracts/UserOperation.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n struct UserOperation {\\n\\n address sender;\\n uint256 nonce;\\n bytes initCode;\\n bytes callData;\\n uint callGas;\\n uint verificationGas;\\n uint preVerificationGas;\\n uint maxFeePerGas;\\n uint maxPriorityFeePerGas;\\n address paymaster;\\n bytes paymasterData;\\n bytes signature;\\n }\\n\\nlibrary UserOperationLib {\\n\\n function getSender(UserOperation calldata userOp) internal view returns (address ret) {\\n assembly {ret := calldataload(userOp)}\\n }\\n\\n //relayer/miner might submit the TX with higher priorityFee, but the user should not\\n // pay above what he signed for.\\n function gasPrice(UserOperation calldata userOp) internal view returns (uint) {\\n unchecked {\\n return min(userOp.maxFeePerGas, userOp.maxPriorityFeePerGas + block.basefee);\\n }\\n }\\n\\n function requiredGas(UserOperation calldata userOp) internal pure returns (uint) {\\n unchecked {\\n return userOp.callGas + userOp.verificationGas + userOp.preVerificationGas;\\n }\\n }\\n\\n function requiredPreFund(UserOperation calldata userOp, uint overhead) internal view returns (uint prefund) {\\n return (requiredGas(userOp) + overhead) * gasPrice(userOp);\\n }\\n\\n function hasPaymaster(UserOperation calldata userOp) internal pure returns (bool) {\\n return userOp.paymaster != address(0);\\n }\\n\\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\\n //lighter signature scheme. must match UserOp.ts#packUserOp\\n bytes calldata sig = userOp.signature;\\n assembly {\\n let ofs := userOp\\n let len := sub(sub(sig.offset, ofs), 32)\\n ret := mload(0x40)\\n mstore(0x40, add(ret, add(len, 32)))\\n mstore(ret, len)\\n calldatacopy(add(ret, 32), ofs, len)\\n }\\n return ret;\\n\\n //TODO: eip712-style ?\\n return abi.encode(\\n userOp.sender,\\n userOp.nonce,\\n keccak256(userOp.initCode),\\n keccak256(userOp.callData),\\n userOp.callGas,\\n userOp.verificationGas,\\n userOp.preVerificationGas,\\n userOp.maxFeePerGas,\\n userOp.maxPriorityFeePerGas,\\n userOp.paymaster,\\n keccak256(userOp.paymasterData)\\n );\\n }\\n\\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(pack(userOp))));\\n }\\n\\n function min(uint a, uint b) internal pure returns (uint) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0x7ea8383b9bbd8cfa5a96f59e1f37c20a681daa798b80d67eb52ade3c53f3ea30\",\"license\":\"GPL-3.0\"},\"contracts/samples/SimpleWallet.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"../IWallet.sol\\\";\\nimport \\\"../EntryPoint.sol\\\";\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n//minimal wallet\\n// this is sample minimal wallet.\\n// has execute, eth handling methods\\n// has a single signer that can send requests through the entryPoint.\\ncontract SimpleWallet is IWallet {\\n using UserOperationLib for UserOperation;\\n struct OwnerNonce {\\n uint96 nonce;\\n address owner;\\n }\\n OwnerNonce ownerNonce;\\n EntryPoint public entryPoint;\\n\\n function nonce() public view returns (uint) {\\n return ownerNonce.nonce;\\n }\\n\\n function owner() public view returns(address) {\\n return ownerNonce.owner;\\n }\\n\\n event EntryPointChanged(EntryPoint oldEntryPoint, EntryPoint newEntryPoint);\\n\\n receive() external payable {}\\n\\n constructor(EntryPoint _entryPoint, address _owner) {\\n entryPoint = _entryPoint;\\n ownerNonce.owner = _owner;\\n }\\n\\n modifier onlyOwner() {\\n _onlyOwner();\\n _;\\n }\\n\\n function _onlyOwner() internal view {\\n //directly from EOA owner, or through the entryPoint (which gets redirected through execFromEntryPoint)\\n require(msg.sender == ownerNonce.owner || msg.sender == address(this), \\\"only owner\\\");\\n }\\n\\n function transfer(address payable dest, uint amount) external onlyOwner {\\n dest.transfer(amount);\\n }\\n\\n function exec(address dest, uint value, bytes calldata func) external onlyOwner {\\n _call(dest, value, func);\\n }\\n\\n function updateEntryPoint(EntryPoint _entryPoint) external onlyOwner {\\n emit EntryPointChanged(entryPoint, _entryPoint);\\n entryPoint = _entryPoint;\\n }\\n\\n function _requireFromEntryPoint() internal view {\\n require(msg.sender == address(entryPoint), \\\"wallet: not from EntryPoint\\\");\\n }\\n\\n function verifyUserOp(UserOperation calldata userOp, uint requiredPrefund) external override {\\n _requireFromEntryPoint();\\n _validateSignature(userOp);\\n _validateAndIncrementNonce(userOp);\\n _payPrefund(requiredPrefund);\\n }\\n\\n function _payPrefund(uint requiredPrefund) internal {\\n if (requiredPrefund != 0) {\\n (bool success) = payable(msg.sender).send(requiredPrefund);\\n (success);\\n //ignore failure (its EntryPoint's job to verify, not wallet.)\\n }\\n }\\n\\n //called by entryPoint, only after verifyUserOp succeeded.\\n function execFromEntryPoint(address dest, uint value, bytes calldata func) external {\\n _requireFromEntryPoint();\\n _call(dest, value, func);\\n }\\n\\n function _validateAndIncrementNonce(UserOperation calldata userOp) internal {\\n //during construction, the \\\"nonce\\\" field hold the salt.\\n // if we assert it is zero, then we allow only a single wallet per owner.\\n if (userOp.initCode.length == 0) {\\n require(ownerNonce.nonce++ == userOp.nonce, \\\"wallet: invalid nonce\\\");\\n }\\n }\\n\\n function _validateSignature(UserOperation calldata userOp) internal view {\\n\\n bytes32 hash = userOp.hash();\\n (bytes32 r, bytes32 s, uint8 v) = _rsv(userOp.signature);\\n\\n require(owner() == _ecrecover(hash, v, r, s), \\\"wallet: wrong signature\\\");\\n }\\n\\n function _rsv(bytes calldata signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\\n\\n require(signature.length == 65, \\\"wallet: invalid signature length\\\");\\n assembly {\\n r := calldataload(signature.offset)\\n s := calldataload(add(signature.offset, 0x20))\\n v := byte(0, calldataload(add(signature.offset, 0x40)))\\n }\\n }\\n\\n function _ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n return ecrecover(hash, v, r, s);\\n }\\n\\n function _call(address sender, uint value, bytes memory data) internal {\\n (bool success, bytes memory result) = sender.call{value : value}(data);\\n if (!success) {\\n assembly {\\n revert(result, add(result, 32))\\n }\\n }\\n }\\n\\n function addDeposit() public payable {\\n entryPoint.addDeposit{value : msg.value}();\\n }\\n\\n function withdrawDeposit(address payable withdrawAddress) public {\\n entryPoint.withdrawStake(withdrawAddress);\\n }\\n}\\n\",\"keccak256\":\"0xf3afea609dd9502a958ce8dbbef6fd2271663c750d356cf911a082f2fa4e7d4b\",\"license\":\"GPL-3.0\"},\"hardhat/console.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\",\"keccak256\":\"0x72b6a1d297cd3b033d7c2e4a7e7864934bb767db6453623f1c3082c6534547f4\",\"license\":\"MIT\"}},\"version\":1}",
+ "bytecode": "0x608060405234801561001057600080fd5b50604051610aed380380610aed83398101604081905261002f91610077565b600180546001600160a01b039384166001600160a01b031990911617905560008054919092166c01000000000000000000000000026001600160601b039091161790556100c9565b6000806040838503121561008a57600080fd5b8251610095816100b1565b60208401519092506100a6816100b1565b809150509250929050565b6001600160a01b03811681146100c657600080fd5b50565b610a15806100d86000396000f3fe6080604052600436106100955760003560e01c80638da5cb5b116100595780638da5cb5b1461012b578063a9059cbb14610169578063affed0e014610189578063b0d691fe146101b0578063fbfb39e0146101d057600080fd5b80630565bb67146100a15780631b71bb6e146100c35780634a58db19146100e357806351e41700146100eb57806380c5c7d01461010b57600080fd5b3661009c57005b600080fd5b3480156100ad57600080fd5b506100c16100bc366004610846565b6101f0565b005b3480156100cf57600080fd5b506100c16100de3660046107f6565b61023f565b6100c16102b0565b3480156100f757600080fd5b506100c16101063660046107f6565b61031b565b34801561011757600080fd5b506100c1610126366004610846565b610362565b34801561013757600080fd5b50600054600160601b90046001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561017557600080fd5b506100c161018436600461081a565b61036a565b34801561019557600080fd5b506000546001600160601b0316604051908152602001610160565b3480156101bc57600080fd5b5060015461014c906001600160a01b031681565b3480156101dc57600080fd5b506100c16101eb3660046108cf565b6103ad565b6101f86103d4565b610239848484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061043392505050565b50505050565b6102476103d4565b600154604080516001600160a01b03928316815291831660208301527f450909c1478d09248269d4ad4fa8cba61ca3f50faed58c7aedefa51c7f62b83a910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b600160009054906101000a90046001600160a01b03166001600160a01b0316634a58db19346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561030057600080fd5b505af1158015610314573d6000803e3d6000fd5b5050505050565b60015460405163611d2e7560e11b81526001600160a01b0383811660048301529091169063c23a5cea90602401600060405180830381600087803b15801561030057600080fd5b6101f86104a2565b6103726103d4565b6040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156103a8573d6000803e3d6000fd5b505050565b6103b56104a2565b6103be826104fc565b6103c7826105ae565b6103d081610658565b5050565b600054600160601b90046001600160a01b03163314806103f357503330145b6104315760405162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b60448201526064015b60405180910390fd5b565b600080846001600160a01b0316848460405161044f919061090c565b60006040518083038185875af1925050503d806000811461048c576040519150601f19603f3d011682016040523d82523d6000602084013e610491565b606091505b509150915081610314576020810181fd5b6001546001600160a01b031633146104315760405162461bcd60e51b815260206004820152601b60248201527f77616c6c65743a206e6f742066726f6d20456e747279506f696e7400000000006044820152606401610428565b600061050782610680565b90506000808061052361051e610160870187610947565b6106e3565b9250925092506105358482858561074f565b6001600160a01b03166105586000546001600160a01b03600160601b9091041690565b6001600160a01b0316146103145760405162461bcd60e51b815260206004820152601760248201527f77616c6c65743a2077726f6e67207369676e61747572650000000000000000006044820152606401610428565b6105bb6040820182610947565b1515905061065557600080546020830135916001600160601b0390911690806105e383610995565b91906101000a8154816001600160601b0302191690836001600160601b031602179055506001600160601b0316146106555760405162461bcd60e51b815260206004820152601560248201527477616c6c65743a20696e76616c6964206e6f6e636560581b6044820152606401610428565b50565b801561065557604051600090339083156108fc0290849084818181858888f150505050505050565b600061068b826107b7565b80516020918201206040517f19457468657265756d205369676e6564204d6573736167653a0a33320000000092810192909252603c820152605c01604051602081830303815290604052805190602001209050919050565b60008080604184146107375760405162461bcd60e51b815260206004820181905260248201527f77616c6c65743a20696e76616c6964207369676e6174757265206c656e6774686044820152606401610428565b50508235936020840135936040013560001a92509050565b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156107a3573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b60603660006107ca610160850185610947565b915091508360208184030360405194506020810185016040528085528082602087013750505050919050565b60006020828403121561080857600080fd5b8135610813816109ca565b9392505050565b6000806040838503121561082d57600080fd5b8235610838816109ca565b946020939093013593505050565b6000806000806060858703121561085c57600080fd5b8435610867816109ca565b935060208501359250604085013567ffffffffffffffff8082111561088b57600080fd5b818701915087601f83011261089f57600080fd5b8135818111156108ae57600080fd5b8860208285010111156108c057600080fd5b95989497505060200194505050565b600080604083850312156108e257600080fd5b823567ffffffffffffffff8111156108f957600080fd5b8301610180818603121561083857600080fd5b6000825160005b8181101561092d5760208186018101518583015201610913565b8181111561093c576000828501525b509190910192915050565b6000808335601e1984360301811261095e57600080fd5b83018035915067ffffffffffffffff82111561097957600080fd5b60200191503681900382131561098e57600080fd5b9250929050565b60006001600160601b03808316818114156109c057634e487b7160e01b600052601160045260246000fd5b6001019392505050565b6001600160a01b038116811461065557600080fdfea264697066735822122060a95252b25b23dd208aa04a5a7d75efffd9ee1f7980d087a2ac978cfed715bd64736f6c63430008070033",
+ "deployedBytecode": "0x6080604052600436106100955760003560e01c80638da5cb5b116100595780638da5cb5b1461012b578063a9059cbb14610169578063affed0e014610189578063b0d691fe146101b0578063fbfb39e0146101d057600080fd5b80630565bb67146100a15780631b71bb6e146100c35780634a58db19146100e357806351e41700146100eb57806380c5c7d01461010b57600080fd5b3661009c57005b600080fd5b3480156100ad57600080fd5b506100c16100bc366004610846565b6101f0565b005b3480156100cf57600080fd5b506100c16100de3660046107f6565b61023f565b6100c16102b0565b3480156100f757600080fd5b506100c16101063660046107f6565b61031b565b34801561011757600080fd5b506100c1610126366004610846565b610362565b34801561013757600080fd5b50600054600160601b90046001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b34801561017557600080fd5b506100c161018436600461081a565b61036a565b34801561019557600080fd5b506000546001600160601b0316604051908152602001610160565b3480156101bc57600080fd5b5060015461014c906001600160a01b031681565b3480156101dc57600080fd5b506100c16101eb3660046108cf565b6103ad565b6101f86103d4565b610239848484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061043392505050565b50505050565b6102476103d4565b600154604080516001600160a01b03928316815291831660208301527f450909c1478d09248269d4ad4fa8cba61ca3f50faed58c7aedefa51c7f62b83a910160405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b600160009054906101000a90046001600160a01b03166001600160a01b0316634a58db19346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561030057600080fd5b505af1158015610314573d6000803e3d6000fd5b5050505050565b60015460405163611d2e7560e11b81526001600160a01b0383811660048301529091169063c23a5cea90602401600060405180830381600087803b15801561030057600080fd5b6101f86104a2565b6103726103d4565b6040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156103a8573d6000803e3d6000fd5b505050565b6103b56104a2565b6103be826104fc565b6103c7826105ae565b6103d081610658565b5050565b600054600160601b90046001600160a01b03163314806103f357503330145b6104315760405162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b60448201526064015b60405180910390fd5b565b600080846001600160a01b0316848460405161044f919061090c565b60006040518083038185875af1925050503d806000811461048c576040519150601f19603f3d011682016040523d82523d6000602084013e610491565b606091505b509150915081610314576020810181fd5b6001546001600160a01b031633146104315760405162461bcd60e51b815260206004820152601b60248201527f77616c6c65743a206e6f742066726f6d20456e747279506f696e7400000000006044820152606401610428565b600061050782610680565b90506000808061052361051e610160870187610947565b6106e3565b9250925092506105358482858561074f565b6001600160a01b03166105586000546001600160a01b03600160601b9091041690565b6001600160a01b0316146103145760405162461bcd60e51b815260206004820152601760248201527f77616c6c65743a2077726f6e67207369676e61747572650000000000000000006044820152606401610428565b6105bb6040820182610947565b1515905061065557600080546020830135916001600160601b0390911690806105e383610995565b91906101000a8154816001600160601b0302191690836001600160601b031602179055506001600160601b0316146106555760405162461bcd60e51b815260206004820152601560248201527477616c6c65743a20696e76616c6964206e6f6e636560581b6044820152606401610428565b50565b801561065557604051600090339083156108fc0290849084818181858888f150505050505050565b600061068b826107b7565b80516020918201206040517f19457468657265756d205369676e6564204d6573736167653a0a33320000000092810192909252603c820152605c01604051602081830303815290604052805190602001209050919050565b60008080604184146107375760405162461bcd60e51b815260206004820181905260248201527f77616c6c65743a20696e76616c6964207369676e6174757265206c656e6774686044820152606401610428565b50508235936020840135936040013560001a92509050565b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa1580156107a3573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b60603660006107ca610160850185610947565b915091508360208184030360405194506020810185016040528085528082602087013750505050919050565b60006020828403121561080857600080fd5b8135610813816109ca565b9392505050565b6000806040838503121561082d57600080fd5b8235610838816109ca565b946020939093013593505050565b6000806000806060858703121561085c57600080fd5b8435610867816109ca565b935060208501359250604085013567ffffffffffffffff8082111561088b57600080fd5b818701915087601f83011261089f57600080fd5b8135818111156108ae57600080fd5b8860208285010111156108c057600080fd5b95989497505060200194505050565b600080604083850312156108e257600080fd5b823567ffffffffffffffff8111156108f957600080fd5b8301610180818603121561083857600080fd5b6000825160005b8181101561092d5760208186018101518583015201610913565b8181111561093c576000828501525b509190910192915050565b6000808335601e1984360301811261095e57600080fd5b83018035915067ffffffffffffffff82111561097957600080fd5b60200191503681900382131561098e57600080fd5b9250929050565b60006001600160601b03808316818114156109c057634e487b7160e01b600052601160045260246000fd5b6001019392505050565b6001600160a01b038116811461065557600080fdfea264697066735822122060a95252b25b23dd208aa04a5a7d75efffd9ee1f7980d087a2ac978cfed715bd64736f6c63430008070033",
+ "devdoc": {
+ "kind": "dev",
+ "methods": {},
+ "version": 1
+ },
+ "userdoc": {
+ "kind": "user",
+ "methods": {},
+ "version": 1
+ },
+ "storageLayout": {
+ "storage": [
+ {
+ "astId": 2814,
+ "contract": "contracts/samples/SimpleWallet.sol:SimpleWallet",
+ "label": "ownerNonce",
+ "offset": 0,
+ "slot": "0",
+ "type": "t_struct(OwnerNonce)2811_storage"
+ },
+ {
+ "astId": 2817,
+ "contract": "contracts/samples/SimpleWallet.sol:SimpleWallet",
+ "label": "entryPoint",
+ "offset": 0,
+ "slot": "1",
+ "type": "t_contract(EntryPoint)2231"
+ }
+ ],
+ "types": {
+ "t_address": {
+ "encoding": "inplace",
+ "label": "address",
+ "numberOfBytes": "20"
+ },
+ "t_contract(EntryPoint)2231": {
+ "encoding": "inplace",
+ "label": "contract EntryPoint",
+ "numberOfBytes": "20"
+ },
+ "t_struct(OwnerNonce)2811_storage": {
+ "encoding": "inplace",
+ "label": "struct SimpleWallet.OwnerNonce",
+ "members": [
+ {
+ "astId": 2808,
+ "contract": "contracts/samples/SimpleWallet.sol:SimpleWallet",
+ "label": "nonce",
+ "offset": 0,
+ "slot": "0",
+ "type": "t_uint96"
+ },
+ {
+ "astId": 2810,
+ "contract": "contracts/samples/SimpleWallet.sol:SimpleWallet",
+ "label": "owner",
+ "offset": 12,
+ "slot": "0",
+ "type": "t_address"
+ }
+ ],
+ "numberOfBytes": "32"
+ },
+ "t_uint96": {
+ "encoding": "inplace",
+ "label": "uint96",
+ "numberOfBytes": "12"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/TestCounter.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/TestCounter.json
new file mode 100644
index 000000000..0dbb2ce01
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/TestCounter.json
@@ -0,0 +1,118 @@
+{
+ "address": "0x4B52ceEDE2e695CAeDBC1Cc8E7f9d5Ef18F0EeF5",
+ "abi": [
+ {
+ "inputs": [],
+ "name": "count",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "counters",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "repeat",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string"
+ }
+ ],
+ "name": "gasWaster",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ],
+ "args": [],
+ "solcInputHash": "9255faacf3ae4e81db1326413027bfa0",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.7+commit.e28d00a7\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"count\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"counters\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repeat\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"gasWaster\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/test/TestCounter.sol\":\"TestCounter\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/IWallet.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\ninterface IWallet {\\n\\n // validate user's signature and nonce\\n // @param requiredPrefund how much this wallet should pre-fund the transaction.\\n // @note that after execution, the excess is sent back to the wallet.\\n // @note if requiredPrefund is zero, the wallet MUST NOT send anything (the paymaster pays)\\n function verifyUserOp(UserOperation calldata userOp, uint requiredPrefund) external;\\n}\\n\",\"keccak256\":\"0x29f98a4e6033cd10007dcc9b569fda950413cc91d8560a67f20a35e8185c9228\",\"license\":\"GPL-3.0\"},\"contracts/UserOperation.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"hardhat/console.sol\\\";\\n\\n struct UserOperation {\\n\\n address sender;\\n uint256 nonce;\\n bytes initCode;\\n bytes callData;\\n uint callGas;\\n uint verificationGas;\\n uint preVerificationGas;\\n uint maxFeePerGas;\\n uint maxPriorityFeePerGas;\\n address paymaster;\\n bytes paymasterData;\\n bytes signature;\\n }\\n\\nlibrary UserOperationLib {\\n\\n function getSender(UserOperation calldata userOp) internal view returns (address ret) {\\n assembly {ret := calldataload(userOp)}\\n }\\n\\n //relayer/miner might submit the TX with higher priorityFee, but the user should not\\n // pay above what he signed for.\\n function gasPrice(UserOperation calldata userOp) internal view returns (uint) {\\n unchecked {\\n return min(userOp.maxFeePerGas, userOp.maxPriorityFeePerGas + block.basefee);\\n }\\n }\\n\\n function requiredGas(UserOperation calldata userOp) internal pure returns (uint) {\\n unchecked {\\n return userOp.callGas + userOp.verificationGas + userOp.preVerificationGas;\\n }\\n }\\n\\n function requiredPreFund(UserOperation calldata userOp, uint overhead) internal view returns (uint prefund) {\\n return (requiredGas(userOp) + overhead) * gasPrice(userOp);\\n }\\n\\n function hasPaymaster(UserOperation calldata userOp) internal pure returns (bool) {\\n return userOp.paymaster != address(0);\\n }\\n\\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\\n //lighter signature scheme. must match UserOp.ts#packUserOp\\n bytes calldata sig = userOp.signature;\\n assembly {\\n let ofs := userOp\\n let len := sub(sub(sig.offset, ofs), 32)\\n ret := mload(0x40)\\n mstore(0x40, add(ret, add(len, 32)))\\n mstore(ret, len)\\n calldatacopy(add(ret, 32), ofs, len)\\n }\\n return ret;\\n\\n //TODO: eip712-style ?\\n return abi.encode(\\n userOp.sender,\\n userOp.nonce,\\n keccak256(userOp.initCode),\\n keccak256(userOp.callData),\\n userOp.callGas,\\n userOp.verificationGas,\\n userOp.preVerificationGas,\\n userOp.maxFeePerGas,\\n userOp.maxPriorityFeePerGas,\\n userOp.paymaster,\\n keccak256(userOp.paymasterData)\\n );\\n }\\n\\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(pack(userOp))));\\n }\\n\\n function min(uint a, uint b) internal pure returns (uint) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0x7ea8383b9bbd8cfa5a96f59e1f37c20a681daa798b80d67eb52ade3c53f3ea30\",\"license\":\"GPL-3.0\"},\"contracts/test/TestCounter.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.7;\\n\\nimport \\\"../UserOperation.sol\\\";\\nimport \\\"../IWallet.sol\\\";\\n\\n//sample \\\"receiver\\\" contract, for testing \\\"exec\\\" from wallet.\\ncontract TestCounter {\\n mapping(address => uint) public counters;\\n\\n function count() public {\\n counters[msg.sender] = counters[msg.sender] + 1;\\n\\n }\\n\\n //helper method to waste gas\\n // repeat - waste gas on writing storage in a loop\\n // junk - dynamic buffer to stress the function size.\\n mapping(uint => uint) xxx;\\n uint offset;\\n\\n function gasWaster(uint repeat, string calldata /*junk*/) external {\\n for (uint i = 1; i <= repeat; i++) {\\n offset++;\\n xxx[offset] = i;\\n }\\n }\\n}\",\"keccak256\":\"0xfa15d72740c6ba7c1aca1925e27774b3701a585e866960ca70460ae55e0ae7d3\",\"license\":\"GPL-3.0\"},\"hardhat/console.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >= 0.4.22 <0.9.0;\\n\\nlibrary console {\\n\\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n\\tfunction _sendLogPayload(bytes memory payload) private view {\\n\\t\\tuint256 payloadLength = payload.length;\\n\\t\\taddress consoleAddress = CONSOLE_ADDRESS;\\n\\t\\tassembly {\\n\\t\\t\\tlet payloadStart := add(payload, 32)\\n\\t\\t\\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n\\t\\t}\\n\\t}\\n\\n\\tfunction log() internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n\\t}\\n\\n\\tfunction logInt(int p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(int)\\\", p0));\\n\\t}\\n\\n\\tfunction logUint(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction logString(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction logBool(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction logAddress(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes(bytes memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes1(bytes1 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes2(bytes2 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes3(bytes3 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes4(bytes4 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes5(bytes5 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes6(bytes6 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes7(bytes7 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes8(bytes8 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes9(bytes9 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes10(bytes10 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes11(bytes11 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes12(bytes12 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes13(bytes13 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes14(bytes14 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes15(bytes15 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes16(bytes16 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes17(bytes17 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes18(bytes18 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes19(bytes19 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes20(bytes20 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes21(bytes21 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes22(bytes22 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes23(bytes23 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes24(bytes24 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes25(bytes25 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes26(bytes26 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes27(bytes27 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes28(bytes28 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes29(bytes29 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes30(bytes30 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes31(bytes31 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n\\t}\\n\\n\\tfunction logBytes32(bytes32 p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint)\\\", p0));\\n\\t}\\n\\n\\tfunction log(string memory p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n\\t}\\n\\n\\tfunction log(bool p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n\\t}\\n\\n\\tfunction log(address p0) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(address p0, address p1) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(uint p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(uint,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(bool p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, uint p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, bool p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, uint p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, bool p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, uint p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, bool p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n\\tfunction log(address p0, address p1, address p2, address p3) internal view {\\n\\t\\t_sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n\\t}\\n\\n}\\n\",\"keccak256\":\"0x72b6a1d297cd3b033d7c2e4a7e7864934bb767db6453623f1c3082c6534547f4\",\"license\":\"MIT\"}},\"version\":1}",
+ "bytecode": "0x608060405234801561001057600080fd5b50610238806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806306661abd14610046578063a1b4689014610050578063be65ab8c14610063575b600080fd5b61004e610095565b005b61004e61005e36600461013d565b6100c2565b61008361007136600461010d565b60006020819052908152604090205481565b60405190815260200160405180910390f35b336000908152602081905260409020546100b09060016101b9565b33600090815260208190526040902055565b60015b83811161010757600280549060006100dc836101d1565b90915550506002546000908152600160205260409020819055806100ff816101d1565b9150506100c5565b50505050565b60006020828403121561011f57600080fd5b81356001600160a01b038116811461013657600080fd5b9392505050565b60008060006040848603121561015257600080fd5b83359250602084013567ffffffffffffffff8082111561017157600080fd5b818601915086601f83011261018557600080fd5b81358181111561019457600080fd5b8760208285010111156101a657600080fd5b6020830194508093505050509250925092565b600082198211156101cc576101cc6101ec565b500190565b60006000198214156101e5576101e56101ec565b5060010190565b634e487b7160e01b600052601160045260246000fdfea26469706673582212202705b7732e8fc4fb811ca9240189d156e252ec8b1aef99971c2fc2cdbeb336d764736f6c63430008070033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806306661abd14610046578063a1b4689014610050578063be65ab8c14610063575b600080fd5b61004e610095565b005b61004e61005e36600461013d565b6100c2565b61008361007136600461010d565b60006020819052908152604090205481565b60405190815260200160405180910390f35b336000908152602081905260409020546100b09060016101b9565b33600090815260208190526040902055565b60015b83811161010757600280549060006100dc836101d1565b90915550506002546000908152600160205260409020819055806100ff816101d1565b9150506100c5565b50505050565b60006020828403121561011f57600080fd5b81356001600160a01b038116811461013657600080fd5b9392505050565b60008060006040848603121561015257600080fd5b83359250602084013567ffffffffffffffff8082111561017157600080fd5b818601915086601f83011261018557600080fd5b81358181111561019457600080fd5b8760208285010111156101a657600080fd5b6020830194508093505050509250925092565b600082198211156101cc576101cc6101ec565b500190565b60006000198214156101e5576101e56101ec565b5060010190565b634e487b7160e01b600052601160045260246000fdfea26469706673582212202705b7732e8fc4fb811ca9240189d156e252ec8b1aef99971c2fc2cdbeb336d764736f6c63430008070033",
+ "devdoc": {
+ "kind": "dev",
+ "methods": {},
+ "version": 1
+ },
+ "userdoc": {
+ "kind": "user",
+ "methods": {},
+ "version": 1
+ },
+ "storageLayout": {
+ "storage": [
+ {
+ "astId": 3638,
+ "contract": "contracts/test/TestCounter.sol:TestCounter",
+ "label": "counters",
+ "offset": 0,
+ "slot": "0",
+ "type": "t_mapping(t_address,t_uint256)"
+ },
+ {
+ "astId": 3658,
+ "contract": "contracts/test/TestCounter.sol:TestCounter",
+ "label": "xxx",
+ "offset": 0,
+ "slot": "1",
+ "type": "t_mapping(t_uint256,t_uint256)"
+ },
+ {
+ "astId": 3660,
+ "contract": "contracts/test/TestCounter.sol:TestCounter",
+ "label": "offset",
+ "offset": 0,
+ "slot": "2",
+ "type": "t_uint256"
+ }
+ ],
+ "types": {
+ "t_address": {
+ "encoding": "inplace",
+ "label": "address",
+ "numberOfBytes": "20"
+ },
+ "t_mapping(t_address,t_uint256)": {
+ "encoding": "mapping",
+ "key": "t_address",
+ "label": "mapping(address => uint256)",
+ "numberOfBytes": "32",
+ "value": "t_uint256"
+ },
+ "t_mapping(t_uint256,t_uint256)": {
+ "encoding": "mapping",
+ "key": "t_uint256",
+ "label": "mapping(uint256 => uint256)",
+ "numberOfBytes": "32",
+ "value": "t_uint256"
+ },
+ "t_uint256": {
+ "encoding": "inplace",
+ "label": "uint256",
+ "numberOfBytes": "32"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/solcInputs/9255faacf3ae4e81db1326413027bfa0.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/solcInputs/9255faacf3ae4e81db1326413027bfa0.json
new file mode 100644
index 000000000..5a05e3bbb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/kovan/solcInputs/9255faacf3ae4e81db1326413027bfa0.json
@@ -0,0 +1,86 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "contracts/EntryPoint.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"./StakeManager.sol\";\nimport \"./UserOperation.sol\";\nimport \"./IWallet.sol\";\nimport \"./IPaymaster.sol\";\n\ninterface ICreate2Deployer {\n function deploy(bytes memory _initCode, bytes32 _salt) external returns (address);\n}\n\ncontract EntryPoint is StakeManager {\n\n using UserOperationLib for UserOperation;\n // paymaster locked stake\n // (actual stake should be higher, to cover actual call cost)\n uint256 constant PAYMASTER_STAKE = 1 ether;\n\n enum PaymentMode {\n paymasterStake, // if paymaster is set, use paymaster's stake to pay.\n walletStake, // wallet has enough stake to pay for request.\n walletEth // wallet has no stake. paying with eth.\n }\n\n uint public immutable perOpOverhead;\n address public immutable create2factory;\n\n event UserOperationEvent(address indexed sender, address indexed paymaster, uint nonce, uint actualGasCost, uint actualGasPrice, bool success);\n event UserOperationRevertReason(address indexed sender, uint nonce, bytes revertReason);\n\n event PaymasterPostOpFailed(address indexed sender, address indexed paymaster, uint nonce, bytes reason);\n\n //handleOps reverts with this error struct, to mark the offending op\n // NOTE: if simulateOp passes successfully, there should be no reason for handleOps to fail on it.\n // @param opIndex - index into the array of ops to the failed one (in simulateOp, this is always zero)\n // @param paymaster - if paymaster.verifyPaymasterUserOp fails, this will be the paymaster's address. if verifyUserOp failed,\n // this value will be zero (since it failed before accessing the paymaster)\n // @param reason - revert reason\n // only to aid troubleshooting of wallet/paymaster reverts\n error FailedOp(uint opIndex, address paymaster, string reason);\n\n constructor(address _create2factory, uint _perOpOverhead, uint32 _unstakeDelayBlocks) StakeManager(_unstakeDelayBlocks) {\n create2factory = _create2factory;\n perOpOverhead = _perOpOverhead;\n }\n\n receive() external payable {}\n\n /**\n * Execute the given UserOperation.\n * @param op the operation to execute\n * @param redeemer the contract to redeem the fee\n */\n function handleOp(UserOperation calldata op, address payable redeemer) public {\n\n uint preGas = gasleft();\n\n (uint256 prefund, PaymentMode paymentMode, bytes memory context) = _validatePrepayment(0, op);\n uint preOpGas = preGas - gasleft() + perOpOverhead;\n\n uint actualGasCost;\n\n try this.internalHandleOp(op, context, preOpGas, prefund, paymentMode) returns (uint _actualGasCost) {\n actualGasCost = _actualGasCost;\n } catch {\n uint actualGas = preGas - gasleft() + preOpGas;\n actualGasCost = handlePostOp(IPaymaster.PostOpMode.postOpReverted, op, context, actualGas, prefund, paymentMode);\n }\n\n redeem(redeemer, actualGasCost);\n }\n\n function redeem(address payable redeemer, uint amount) internal {\n redeemer.transfer(amount);\n }\n\n function handleOps(UserOperation[] calldata ops, address payable redeemer) public {\n\n uint opslen = ops.length;\n uint256[] memory preOpGas = new uint256[](opslen);\n bytes32[] memory contexts = new bytes32[](opslen);\n uint256[] memory prefunds = new uint256[](opslen);\n PaymentMode[] memory paymentModes = new PaymentMode[](opslen);\n\n for (uint i = 0; i < opslen; i++) {\n uint preGas = gasleft();\n UserOperation calldata op = ops[i];\n\n bytes memory context;\n bytes32 contextOffset;\n (prefunds[i], paymentModes[i], context) = _validatePrepayment(i, op);\n assembly {contextOffset := context}\n contexts[i] = contextOffset;\n preOpGas[i] = preGas - gasleft() + perOpOverhead;\n }\n\n uint collected = 0;\n\n for (uint i = 0; i < ops.length; i++) {\n uint preGas = gasleft();\n UserOperation calldata op = ops[i];\n bytes32 contextOffset = contexts[i];\n bytes memory context;\n assembly {context := contextOffset}\n uint preOpGasi = preOpGas[i];\n uint prefundi = prefunds[i];\n PaymentMode paymentModei = paymentModes[i];\n\n try this.internalHandleOp(op, context, preOpGasi, prefundi, paymentModei) returns (uint _actualGasCost) {\n collected += _actualGasCost;\n } catch {\n uint actualGas = preGas - gasleft() + preOpGasi;\n collected += handlePostOp(IPaymaster.PostOpMode.postOpReverted, op, context, actualGas, prefundi, paymentModei);\n }\n }\n\n redeem(redeemer, collected);\n }\n\n function internalHandleOp(UserOperation calldata op, bytes calldata context, uint preOpGas, uint prefund, PaymentMode paymentMode) external returns (uint actualGasCost) {\n uint preGas = gasleft();\n require(msg.sender == address(this));\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (op.callData.length > 0) {\n\n (bool success,bytes memory result) = address(op.getSender()).call{gas : op.callGas}(op.callData);\n if (!success && result.length > 0) {\n emit UserOperationRevertReason(op.getSender(), op.nonce, result);\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n uint actualGas = preGas - gasleft() + preOpGas;\n return handlePostOp(mode, op, context, actualGas, prefund, paymentMode);\n }\n\n /**\n * Simulate a call for wallet.verifyUserOp.\n * Call must not revert.\n * @return gasUsedByPayForSelfOp - gas used by the validation, to pass into simulatePaymasterValidation.\n * The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the wallet's data\n */\n function simulateWalletValidation(UserOperation calldata userOp) external returns (uint gasUsedByPayForSelfOp){\n require(msg.sender == address(0), \"must be called off-chain with from=zero-addr\");\n (uint requiredPreFund, PaymentMode paymentMode) = getPaymentInfo(userOp);\n (gasUsedByPayForSelfOp,) = _validateWalletPrepayment(0, userOp, requiredPreFund, paymentMode);\n }\n\n function getPaymentInfo(UserOperation calldata userOp) internal view returns (uint requiredPrefund, PaymentMode paymentMode) {\n requiredPrefund = userOp.requiredPreFund(perOpOverhead);\n if (userOp.hasPaymaster()) {\n paymentMode = PaymentMode.paymasterStake;\n } else if (isStaked(userOp.getSender(), requiredPrefund, 0)) {\n paymentMode = PaymentMode.walletStake;\n } else {\n paymentMode = PaymentMode.walletEth;\n }\n }\n\n /**\n * Simulate a call to paymaster.verifyPaymasterUserOp\n * do nothing if has no paymaster.\n * @param userOp the user operation to validate.\n * @param gasUsedByPayForSelfOp - the gas returned by simulateWalletValidation, as these 2 calls should share\n * the same userOp.validationGas quota.\n * The node must also verify it doesn't use banned opcode, and that it doesn't reference storage outside the paymaster's data\n */\n function simulatePaymasterValidation(UserOperation calldata userOp, uint gasUsedByPayForSelfOp) external view returns (bytes memory context, uint gasUsedByPayForOp){\n (uint requiredPreFund, PaymentMode paymentMode) = getPaymentInfo(userOp);\n if (paymentMode != PaymentMode.paymasterStake) {\n return (\"\", 0);\n }\n return _validatePaymasterPrepayment(0, userOp, requiredPreFund, gasUsedByPayForSelfOp);\n }\n\n // get the sender address, or use \"create2\" to create it.\n // note that the gas allocation for this creation is deterministic (by the size of callData),\n // so it is not checked on-chain, and adds to the gas used by verifyUserOp\n function _createSenderIfNeeded(UserOperation calldata op) internal {\n if (op.initCode.length != 0) {\n //its a create operation. run the create2\n // note that we're still under the gas limit of validate, so probably\n // this create2 creates a proxy account.\n // appending signer makes the request unique, so no one else can make this request.\n //nonce is meaningless during create, so we re-purpose it as salt\n address sender1 = ICreate2Deployer(create2factory).deploy(op.initCode, bytes32(op.nonce));\n require(sender1 != address(0), \"create2 failed\");\n require(sender1 == op.getSender(), \"sender doesn't match create2 address\");\n }\n }\n\n //get counterfactual sender address.\n // use the initCode and salt in the UserOperation tot create this sender contract\n function getSenderAddress(bytes memory initCode, uint _salt) public view returns (address) {\n bytes32 hash = keccak256(\n abi.encodePacked(\n bytes1(0xff),\n address(create2factory),\n _salt,\n keccak256(initCode)\n )\n );\n\n // NOTE: cast last 20 bytes of hash to address\n return address(uint160(uint256(hash)));\n }\n\n //call wallet.verifyUserOp, and validate that it paid as needed.\n // return actual value sent from wallet to \"this\"\n function _validateWalletPrepayment(uint opIndex, UserOperation calldata op, uint requiredPrefund, PaymentMode paymentMode) internal returns (uint gasUsedByPayForSelfOp, uint prefund) {\n uint preGas = gasleft();\n _createSenderIfNeeded(op);\n uint preBalance = address(this).balance;\n uint requiredEthPrefund = 0;\n if (paymentMode == PaymentMode.walletEth) {\n requiredEthPrefund = requiredPrefund;\n } else if (paymentMode == PaymentMode.walletStake) {\n _prefundFromSender(op, requiredPrefund);\n } else {\n // paymaster pays in handlePostOp\n }\n try IWallet(op.getSender()).verifyUserOp{gas : op.verificationGas}(op, requiredEthPrefund) {\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, address(0), revertReason);\n } catch {\n revert FailedOp(opIndex, address(0), \"\");\n }\n uint actualEthPrefund = address(this).balance - preBalance;\n\n if (paymentMode == PaymentMode.walletEth) {\n if (actualEthPrefund < requiredEthPrefund) {\n revert FailedOp(opIndex, address(0), \"wallet didn't pay prefund\");\n }\n prefund = actualEthPrefund;\n } else if (paymentMode == PaymentMode.walletStake) {\n if (actualEthPrefund != 0) {\n revert FailedOp(opIndex, address(0), \"using wallet stake but wallet paid eth\");\n }\n prefund = requiredPrefund;\n } else {\n if (actualEthPrefund != 0) {\n revert FailedOp(opIndex, address(0), \"has paymaster but wallet paid\");\n }\n prefund = requiredPrefund;\n }\n\n gasUsedByPayForSelfOp = preGas - gasleft();\n }\n\n //validate paymaster.verifyPaymasterUserOp\n function _validatePaymasterPrepayment(uint opIndex, UserOperation calldata op, uint requiredPreFund, uint gasUsedByPayForSelfOp) internal view returns (bytes memory context, uint gasUsedByPayForOp) {\n uint preGas = gasleft();\n if (!isValidStake(op, requiredPreFund)) {\n revert FailedOp(opIndex, op.paymaster, \"not enough stake\");\n }\n //no pre-pay from paymaster\n uint gas = op.verificationGas - gasUsedByPayForSelfOp;\n try IPaymaster(op.paymaster).verifyPaymasterUserOp{gas : gas}(op, requiredPreFund) returns (bytes memory _context){\n context = _context;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, op.paymaster, revertReason);\n } catch {\n revert FailedOp(opIndex, op.paymaster, \"\");\n }\n gasUsedByPayForOp = preGas - gasleft();\n }\n\n function _validatePrepayment(uint opIndex, UserOperation calldata userOp) private returns (uint prefund, PaymentMode paymentMode, bytes memory context){\n\n uint preGas = gasleft();\n uint gasUsedByPayForSelfOp;\n uint requiredPreFund;\n (requiredPreFund, paymentMode) = getPaymentInfo(userOp);\n\n (gasUsedByPayForSelfOp, prefund) = _validateWalletPrepayment(opIndex, userOp, requiredPreFund, paymentMode);\n\n uint gasUsedByPayForOp = 0;\n if (paymentMode == PaymentMode.paymasterStake) {\n (context, gasUsedByPayForOp) = _validatePaymasterPrepayment(opIndex, userOp, requiredPreFund, gasUsedByPayForSelfOp);\n } else {\n context = \"\";\n }\n uint gasUsed = preGas - gasleft();\n\n if (userOp.verificationGas < gasUsed) {\n revert FailedOp(opIndex, userOp.paymaster, \"Used more than verificationGas\");\n }\n }\n\n function getPaymastersStake(address[] calldata paymasters) external view returns (uint[] memory _stakes) {\n _stakes = new uint[](paymasters.length);\n for (uint i = 0; i < paymasters.length; i++) {\n _stakes[i] = stakes[paymasters[i]].stake;\n }\n }\n\n function handlePostOp(IPaymaster.PostOpMode mode, UserOperation calldata op, bytes memory context, uint actualGas, uint prefund, PaymentMode paymentMode) private returns (uint actualGasCost) {\n uint preGas = gasleft();\n uint gasPrice = UserOperationLib.gasPrice(op);\n actualGasCost = actualGas * gasPrice;\n if (paymentMode != PaymentMode.paymasterStake) {\n if (prefund < actualGasCost) {\n revert (\"wallet prefund below actualGasCost\");\n }\n uint refund = prefund - actualGasCost;\n if (paymentMode == PaymentMode.walletStake) {\n _refundSenderStake(op, refund);\n } else {\n _refundSender(op, refund);\n }\n } else {\n if (context.length > 0) {\n //if paymaster.postOp reverts:\n // - emit a message (just for sake of debugging of this poor paymaster)\n // - paymaster still pays (from its stake)\n try IPaymaster(op.paymaster).postOp(mode, context, actualGasCost) {}\n catch (bytes memory errdata) {\n emit PaymasterPostOpFailed(op.getSender(), op.paymaster, op.nonce, errdata);\n }\n }\n //paymaster pays for full gas, including for postOp (and revert event)\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n //paymaster balance known to be high enough, and to be locked for this block\n stakes[op.paymaster].stake -= uint96(actualGasCost);\n }\n _emitLog(op, actualGasCost, gasPrice, mode == IPaymaster.PostOpMode.opSucceeded);\n }\n\n function _emitLog(UserOperation calldata op, uint actualGasCost, uint gasPrice, bool success) internal {\n emit UserOperationEvent(op.getSender(), op.paymaster, op.nonce, actualGasCost, gasPrice, success);\n }\n\n function _prefundFromSender(UserOperation calldata userOp, uint requiredPrefund) internal {\n stakes[userOp.getSender()].stake -= uint96(requiredPrefund);\n }\n\n function _refundSender(UserOperation calldata userOp, uint refund) internal {\n //NOTE: deliberately ignoring revert: wallet should accept refund.\n bool sendOk = payable(userOp.getSender()).send(refund);\n (sendOk);\n }\n function _refundSenderStake(UserOperation calldata userOp, uint refund) internal {\n stakes[userOp.getSender()].stake += uint96(refund);\n }\n\n function isValidStake(UserOperation calldata userOp, uint requiredPreFund) internal view returns (bool) {\n return isPaymasterStaked(userOp.paymaster, PAYMASTER_STAKE + requiredPreFund);\n }\n\n function isPaymasterStaked(address paymaster, uint stake) public view returns (bool) {\n return isStaked(paymaster, stake, unstakeDelayBlocks);\n }\n\n function isContractDeployed(address addr) external view returns (bool) {\n bytes32 hash;\n assembly {\n hash := extcodehash(addr)\n }\n return hash != bytes32(0);\n }\n}\n\n"
+ },
+ "contracts/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8;\n\nimport \"hardhat/console.sol\";\n\ncontract StakeManager {\n\n /// minimum number of blocks to after 'unlock' before amount can be withdrawn.\n uint32 immutable public unstakeDelayBlocks;\n\n constructor(uint32 _unstakeDelayBlocks) {\n unstakeDelayBlocks = _unstakeDelayBlocks;\n }\n\n event StakeAdded(\n address indexed paymaster,\n uint256 totalStake,\n uint256 unstakeDelayBlocks\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocking(\n address indexed paymaster,\n uint256 withdrawBlock\n );\n\n event StakeWithdrawn(\n address indexed paymaster,\n address withdrawAddress,\n uint256 amount\n );\n\n /// @param stake - amount of ether staked for this paymaster\n /// @param withdrawStake - once 'unlocked' the value is no longer staked.\n /// @param withdrawBlock - first block number 'withdraw' will be callable, or zero if the unlock has not been called\n struct StakeInfo {\n uint96 stake;\n uint32 unstakeDelayBlocks;\n uint96 withdrawStake;\n uint32 withdrawBlock;\n }\n\n /// maps relay managers to their stakes\n mapping(address => StakeInfo) public stakes;\n\n function getStakeInfo(address paymaster) external view returns (StakeInfo memory stakeInfo) {\n return stakes[paymaster];\n }\n\n /**\n * add a deposit (just like stake, but with lock=0\n * cancel any pending unlock\n */\n function addDeposit() external payable {\n addStake(0);\n }\n\n //add deposit to another account (doesn't change lock status)\n function addDepositTo(address target) external payable {\n stakes[target].stake += uint96(msg.value);\n }\n\n /**\n * add stake value for this paymaster.\n * cancel any pending unlock\n */\n function addStake(uint32 _unstakeDelayBlocks) public payable {\n require(_unstakeDelayBlocks >= stakes[msg.sender].unstakeDelayBlocks, \"cannot decrease unstake blocks\");\n uint96 stake = uint96(stakes[msg.sender].stake + msg.value + stakes[msg.sender].withdrawStake);\n stakes[msg.sender] = StakeInfo(\n stake,\n _unstakeDelayBlocks,\n 0,\n 0);\n emit StakeAdded(msg.sender, stake, _unstakeDelayBlocks);\n }\n\n function unlockStake() external {\n StakeInfo storage info = stakes[msg.sender];\n require(info.withdrawBlock == 0, \"already pending\");\n require(info.stake != 0 && info.unstakeDelayBlocks != 0, \"no stake to unlock\");\n uint32 withdrawBlock = uint32(block.number) + info.unstakeDelayBlocks;\n info.withdrawBlock = withdrawBlock;\n info.withdrawStake = info.stake;\n info.stake = 0;\n emit StakeUnlocking(msg.sender, withdrawBlock);\n }\n\n function withdrawStake(address payable withdrawAddress) external {\n StakeInfo memory info = stakes[msg.sender];\n if (info.unstakeDelayBlocks != 0) {\n require(info.withdrawStake > 0, \"no unlocked stake\");\n require(info.withdrawBlock <= block.number, \"Withdrawal is not due\");\n }\n uint256 amount = info.withdrawStake + info.stake;\n stakes[msg.sender] = StakeInfo(0, info.unstakeDelayBlocks, 0, 0);\n withdrawAddress.transfer(amount);\n emit StakeWithdrawn(msg.sender, withdrawAddress, amount);\n }\n\n function isStaked(address paymaster, uint requiredStake, uint requiredDelayBlocks) public view returns (bool) {\n StakeInfo memory stakeInfo = stakes[paymaster];\n return stakeInfo.stake >= requiredStake && stakeInfo.unstakeDelayBlocks >= requiredDelayBlocks;\n }\n}\n"
+ },
+ "contracts/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"hardhat/console.sol\";\n\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint callGas;\n uint verificationGas;\n uint preVerificationGas;\n uint maxFeePerGas;\n uint maxPriorityFeePerGas;\n address paymaster;\n bytes paymasterData;\n bytes signature;\n }\n\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal view returns (address ret) {\n assembly {ret := calldataload(userOp)}\n }\n\n //relayer/miner might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint) {\n unchecked {\n return min(userOp.maxFeePerGas, userOp.maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function requiredGas(UserOperation calldata userOp) internal pure returns (uint) {\n unchecked {\n return userOp.callGas + userOp.verificationGas + userOp.preVerificationGas;\n }\n }\n\n function requiredPreFund(UserOperation calldata userOp, uint overhead) internal view returns (uint prefund) {\n return (requiredGas(userOp) + overhead) * gasPrice(userOp);\n }\n\n function hasPaymaster(UserOperation calldata userOp) internal pure returns (bool) {\n return userOp.paymaster != address(0);\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n //lighter signature scheme. must match UserOp.ts#packUserOp\n bytes calldata sig = userOp.signature;\n assembly {\n let ofs := userOp\n let len := sub(sub(sig.offset, ofs), 32)\n ret := mload(0x40)\n mstore(0x40, add(ret, add(len, 32)))\n mstore(ret, len)\n calldatacopy(add(ret, 32), ofs, len)\n }\n return ret;\n\n //TODO: eip712-style ?\n return abi.encode(\n userOp.sender,\n userOp.nonce,\n keccak256(userOp.initCode),\n keccak256(userOp.callData),\n userOp.callGas,\n userOp.verificationGas,\n userOp.preVerificationGas,\n userOp.maxFeePerGas,\n userOp.maxPriorityFeePerGas,\n userOp.paymaster,\n keccak256(userOp.paymasterData)\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\",\n keccak256(pack(userOp))));\n }\n\n function min(uint a, uint b) internal pure returns (uint) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/IWallet.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"./UserOperation.sol\";\n\ninterface IWallet {\n\n // validate user's signature and nonce\n // @param requiredPrefund how much this wallet should pre-fund the transaction.\n // @note that after execution, the excess is sent back to the wallet.\n // @note if requiredPrefund is zero, the wallet MUST NOT send anything (the paymaster pays)\n function verifyUserOp(UserOperation calldata userOp, uint requiredPrefund) external;\n}\n"
+ },
+ "contracts/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"./UserOperation.sol\";\n\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now its a 2nd call, after user's op was deliberately reverted.\n }\n // payment validation: check if paymaster agree to pay (using its stake)\n // revert to reject this request.\n // actual payment is done after postOp is called, by deducting actual call cost form the paymaster's stake.\n // @param userOp the user operation\n // @param maxcost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n // @returns context value to send to a postOp\n // zero length to signify postOp is not required.\n function verifyPaymasterUserOp(UserOperation calldata userOp, uint maxcost) external view returns (bytes memory context);\n\n // post-operation handler.\n // @param mode\n // opSucceeded - user operation succeeded.\n // opReverted - user op reverted. still has to pay for gas.\n // postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n // Now this is the 2nd call, after user's op was deliberately reverted.\n // @param context - the context value returned by verifyPaymasterUserOp\n // @param actualGasCost - actual gas used so far (without this postOp call).\n function postOp(PostOpMode mode, bytes calldata context, uint actualGasCost) external;\n}\n"
+ },
+ "hardhat/console.sol": {
+ "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.4.22 <0.9.0;\n\nlibrary console {\n\taddress constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n\tfunction _sendLogPayload(bytes memory payload) private view {\n\t\tuint256 payloadLength = payload.length;\n\t\taddress consoleAddress = CONSOLE_ADDRESS;\n\t\tassembly {\n\t\t\tlet payloadStart := add(payload, 32)\n\t\t\tlet r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n\t\t}\n\t}\n\n\tfunction log() internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log()\"));\n\t}\n\n\tfunction logInt(int p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(int)\", p0));\n\t}\n\n\tfunction logUint(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction logString(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction logBool(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction logAddress(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction logBytes(bytes memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n\t}\n\n\tfunction logBytes1(bytes1 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n\t}\n\n\tfunction logBytes2(bytes2 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n\t}\n\n\tfunction logBytes3(bytes3 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n\t}\n\n\tfunction logBytes4(bytes4 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n\t}\n\n\tfunction logBytes5(bytes5 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n\t}\n\n\tfunction logBytes6(bytes6 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n\t}\n\n\tfunction logBytes7(bytes7 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n\t}\n\n\tfunction logBytes8(bytes8 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n\t}\n\n\tfunction logBytes9(bytes9 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n\t}\n\n\tfunction logBytes10(bytes10 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n\t}\n\n\tfunction logBytes11(bytes11 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n\t}\n\n\tfunction logBytes12(bytes12 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n\t}\n\n\tfunction logBytes13(bytes13 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n\t}\n\n\tfunction logBytes14(bytes14 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n\t}\n\n\tfunction logBytes15(bytes15 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n\t}\n\n\tfunction logBytes16(bytes16 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n\t}\n\n\tfunction logBytes17(bytes17 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n\t}\n\n\tfunction logBytes18(bytes18 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n\t}\n\n\tfunction logBytes19(bytes19 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n\t}\n\n\tfunction logBytes20(bytes20 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n\t}\n\n\tfunction logBytes21(bytes21 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n\t}\n\n\tfunction logBytes22(bytes22 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n\t}\n\n\tfunction logBytes23(bytes23 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n\t}\n\n\tfunction logBytes24(bytes24 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n\t}\n\n\tfunction logBytes25(bytes25 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n\t}\n\n\tfunction logBytes26(bytes26 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n\t}\n\n\tfunction logBytes27(bytes27 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n\t}\n\n\tfunction logBytes28(bytes28 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n\t}\n\n\tfunction logBytes29(bytes29 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n\t}\n\n\tfunction logBytes30(bytes30 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n\t}\n\n\tfunction logBytes31(bytes31 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n\t}\n\n\tfunction logBytes32(bytes32 p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n\t}\n\n\tfunction log(uint p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint)\", p0));\n\t}\n\n\tfunction log(string memory p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n\t}\n\n\tfunction log(bool p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n\t}\n\n\tfunction log(address p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n\t}\n\n\tfunction log(uint p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n\t}\n\n\tfunction log(string memory p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n\t}\n\n\tfunction log(bool p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n\t}\n\n\tfunction log(address p0, uint p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint)\", p0, p1));\n\t}\n\n\tfunction log(address p0, string memory p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n\t}\n\n\tfunction log(address p0, bool p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n\t}\n\n\tfunction log(address p0, address p1) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(bool p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, uint p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, bool p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, uint p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, bool p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n\t}\n\n\tfunction log(address p0, address p1, address p2) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(uint p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(uint,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(string memory p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(bool p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, uint p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,uint,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, string memory p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, bool p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, uint p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, string memory p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, bool p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, uint p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, string memory p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, bool p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n\t}\n\n\tfunction log(address p0, address p1, address p2, address p3) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n\t}\n\n}\n"
+ },
+ "contracts/samples/VerifyingPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"../IPaymaster.sol\";\nimport \"../EntryPoint.sol\";\n\n/**\n * A sample paymaster that uses external service to decide whether to pay for the UserOp.\n * The paymaster trusts an external signer to sign the transaction.\n * The calling user must pass the UserOp to that external signer first, which performs\n * whatever off-chain verification before signing the UserOp.\n * Note that this signature is NOT a replacement for wallet signature:\n * - the paymaster signs to agree to PAY for GAS.\n * - the wallet signs to prove identity and wallet ownership.\n */\ncontract VerifyingPaymaster is IPaymaster {\n\n using UserOperationLib for UserOperation;\n\n EntryPoint public immutable entryPoint;\n address public immutable verifyingSigner;\n\n constructor(EntryPoint _entryPoint, address _verifyingSigner) {\n entryPoint = _entryPoint;\n verifyingSigner = _verifyingSigner;\n }\n\n function addStake() external payable {\n entryPoint.addStake{value : msg.value}(entryPoint.unstakeDelayBlocks());\n }\n\n // verify our external signer signed this request.\n // the \"paymasterData\" is supposed to be a signature over the entire request params\n function verifyPaymasterUserOp(UserOperation calldata userOp, uint requiredPreFund) external view override returns (bytes memory context) {\n (requiredPreFund);\n\n bytes32 hash = userOp.hash();\n require( userOp.paymasterData.length >= 65, \"VerifyingPaymaster: invalid signature length in paymasterData\");\n (bytes32 r, bytes32 s) = abi.decode(userOp.paymasterData, (bytes32, bytes32));\n uint8 v = uint8(userOp.paymasterData[64]);\n require(verifyingSigner == ecrecover(hash, v, r, s), \"VerifyingPaymaster: wrong signature\");\n\n //no other on-chain validation: entire UserOp should have been checked by the external service,\n // prior signing it.\n return \"\";\n }\n\n function postOp(PostOpMode, bytes calldata, uint) external pure override {\n //should never get called. returned \"0\" from verifyPaymasterUserOp\n revert();\n }\n}\n"
+ },
+ "contracts/samples/TokenPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../IPaymaster.sol\";\nimport \"../EntryPoint.sol\";\nimport \"./SimpleWalletForTokens.sol\";\nimport \"hardhat/console.sol\";\n\n/**\n * A sample paymaster that define itself as a token to pay for gas.\n * The paymaster IS the token to use, since a paymaster cannot use an external contract.\n * also, the exchange rate has to be fixed, since it can't refernce external Uniswap os other exchange contract.\n */\ncontract TokenPaymaster is Ownable, ERC20, IPaymaster {\n\n //calculated cost of the postOp\n uint COST_OF_POST = 3000;\n\n EntryPoint entryPoint;\n bytes32 immutable knownWallet;\n\n constructor(string memory _symbol, EntryPoint _entryPoint) ERC20(_symbol, _symbol) {\n entryPoint = _entryPoint;\n knownWallet = keccak256(type(SimpleWallet).creationCode);\n// knownWallets[keccak256(type(SimpleWallet).creationCode)] = true;\n approve(owner(), type(uint).max);\n }\n\n //helpers for owner, to mint and withdraw tokens.\n function mintTokens(address recipient, uint amount) external onlyOwner {\n _mint(recipient, amount);\n }\n\n //owner should call and put eth into it.\n function addStake() external payable {\n entryPoint.addStake{value : msg.value}(entryPoint.unstakeDelayBlocks());\n }\n\n //TODO: this method assumes a fixed ratio of token-to-eth. should use oracle.\n function ethToToken(uint valueEth) internal pure returns (uint valueToken) {\n return valueEth / 100;\n }\n\n // verify that the user has enough tokens.\n function verifyPaymasterUserOp(UserOperation calldata userOp, uint requiredPreFund) external view override returns (bytes memory context) {\n uint tokenPrefund = ethToToken(requiredPreFund);\n\n if (userOp.initCode.length != 0) {\n bytes32 bytecodeHash = keccak256(userOp.initCode[0:userOp.initCode.length-64]);\n require(knownWallet == bytecodeHash, \"TokenPaymaster: unknown wallet constructor\");\n\n //verify the token constructor params:\n // first param (of 2) should be our entryPoint\n bytes32 entryPointParam = bytes32(userOp.initCode[userOp.initCode.length-64:]);\n require( address(uint160(uint256(entryPointParam))) == address(entryPoint), \"wrong paymaster in constructor\");\n\n //TODO: must also whitelist init function (callData), since that what will call \"token.approve(paymaster)\"\n //no \"allowance\" check during creation (we trust known constructor/init function)\n require(balanceOf(userOp.sender) > tokenPrefund, \"TokenPaymaster: no balance (pre-create)\");\n } else {\n\n require(balanceOf(userOp.sender) > tokenPrefund, \"TokenPaymaster: no balance\");\n }\n\n //since we ARE the token, we don't need approval to _transfer() value from user's balance.\n // if (token.allowance(userOp.sender, address(this)) < tokenPrefund) {\n //\n // //TODO: allowance too low. just before reverting, can check if current operation is \"token.approve(paymaster)\"\n // // this is a multi-step operation: first, verify \"callData\" is exec(token, innerData)\n // // (this requires knowing the \"execute\" signature of the wallet\n // // then verify that \"innerData\" is approve(paymaster,-1)\n // revert(\"TokenPaymaster: no allowance\");\n // }\n return abi.encode(userOp.sender);\n }\n\n //actual charge of user.\n // this method will be called just after the user's TX with postRevert=false.\n // BUT: if the user changed its balance and that postOp reverted, then it gets called again, after reverting\n // the user's TX\n function postOp(PostOpMode mode, bytes calldata context, uint actualGasCost) external override {\n //we don't really care about the mode, we just pay the gas with the user's tokens.\n (mode);\n address sender = abi.decode(context, (address));\n uint charge = ethToToken(actualGasCost + COST_OF_POST);\n //actualGasCost is known to be no larger than the above requiredPreFund, so the transfer should succeed.\n _transfer(sender, address(this), charge);\n }\n}\n"
+ },
+ "@openzeppelin/contracts/access/Ownable.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _setOwner(_msgSender());\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _setOwner(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _setOwner(newOwner);\n }\n\n function _setOwner(address newOwner) private {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n\n uint256 currentAllowance = _allowances[sender][_msgSender()];\n require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n unchecked {\n _approve(sender, _msgSender(), currentAllowance - amount);\n }\n\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n uint256 currentAllowance = _allowances[_msgSender()][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n uint256 senderBalance = _balances[sender];\n require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[sender] = senderBalance - amount;\n }\n _balances[recipient] += amount;\n\n emit Transfer(sender, recipient, amount);\n\n _afterTokenTransfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n"
+ },
+ "contracts/samples/SimpleWalletForTokens.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"./SimpleWallet.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n//in order to be created with tokens, the wallet has to have allowance to the paymaster in advance.\n// the simplest strategy is assign the allowance in the constructor or init function\ncontract SimpleWalletForTokens is SimpleWallet {\n\n constructor(EntryPoint _entryPoint, address _owner, IERC20 token, address paymaster) SimpleWallet(_entryPoint, _owner) {\n token.approve(paymaster, type(uint).max);\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/Context.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n"
+ },
+ "contracts/samples/SimpleWallet.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"../IWallet.sol\";\nimport \"../EntryPoint.sol\";\n\nimport \"hardhat/console.sol\";\n\n//minimal wallet\n// this is sample minimal wallet.\n// has execute, eth handling methods\n// has a single signer that can send requests through the entryPoint.\ncontract SimpleWallet is IWallet {\n using UserOperationLib for UserOperation;\n struct OwnerNonce {\n uint96 nonce;\n address owner;\n }\n OwnerNonce ownerNonce;\n EntryPoint public entryPoint;\n\n function nonce() public view returns (uint) {\n return ownerNonce.nonce;\n }\n\n function owner() public view returns(address) {\n return ownerNonce.owner;\n }\n\n event EntryPointChanged(EntryPoint oldEntryPoint, EntryPoint newEntryPoint);\n\n receive() external payable {}\n\n constructor(EntryPoint _entryPoint, address _owner) {\n entryPoint = _entryPoint;\n ownerNonce.owner = _owner;\n }\n\n modifier onlyOwner() {\n _onlyOwner();\n _;\n }\n\n function _onlyOwner() internal view {\n //directly from EOA owner, or through the entryPoint (which gets redirected through execFromEntryPoint)\n require(msg.sender == ownerNonce.owner || msg.sender == address(this), \"only owner\");\n }\n\n function transfer(address payable dest, uint amount) external onlyOwner {\n dest.transfer(amount);\n }\n\n function exec(address dest, uint value, bytes calldata func) external onlyOwner {\n _call(dest, value, func);\n }\n\n function updateEntryPoint(EntryPoint _entryPoint) external onlyOwner {\n emit EntryPointChanged(entryPoint, _entryPoint);\n entryPoint = _entryPoint;\n }\n\n function _requireFromEntryPoint() internal view {\n require(msg.sender == address(entryPoint), \"wallet: not from EntryPoint\");\n }\n\n function verifyUserOp(UserOperation calldata userOp, uint requiredPrefund) external override {\n _requireFromEntryPoint();\n _validateSignature(userOp);\n _validateAndIncrementNonce(userOp);\n _payPrefund(requiredPrefund);\n }\n\n function _payPrefund(uint requiredPrefund) internal {\n if (requiredPrefund != 0) {\n (bool success) = payable(msg.sender).send(requiredPrefund);\n (success);\n //ignore failure (its EntryPoint's job to verify, not wallet.)\n }\n }\n\n //called by entryPoint, only after verifyUserOp succeeded.\n function execFromEntryPoint(address dest, uint value, bytes calldata func) external {\n _requireFromEntryPoint();\n _call(dest, value, func);\n }\n\n function _validateAndIncrementNonce(UserOperation calldata userOp) internal {\n //during construction, the \"nonce\" field hold the salt.\n // if we assert it is zero, then we allow only a single wallet per owner.\n if (userOp.initCode.length == 0) {\n require(ownerNonce.nonce++ == userOp.nonce, \"wallet: invalid nonce\");\n }\n }\n\n function _validateSignature(UserOperation calldata userOp) internal view {\n\n bytes32 hash = userOp.hash();\n (bytes32 r, bytes32 s, uint8 v) = _rsv(userOp.signature);\n\n require(owner() == _ecrecover(hash, v, r, s), \"wallet: wrong signature\");\n }\n\n function _rsv(bytes calldata signature) internal pure returns (bytes32 r, bytes32 s, uint8 v) {\n\n require(signature.length == 65, \"wallet: invalid signature length\");\n assembly {\n r := calldataload(signature.offset)\n s := calldataload(add(signature.offset, 0x20))\n v := byte(0, calldataload(add(signature.offset, 0x40)))\n }\n }\n\n function _ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n return ecrecover(hash, v, r, s);\n }\n\n function _call(address sender, uint value, bytes memory data) internal {\n (bool success, bytes memory result) = sender.call{value : value}(data);\n if (!success) {\n assembly {\n revert(result, add(result, 32))\n }\n }\n }\n\n function addDeposit() public payable {\n entryPoint.addDeposit{value : msg.value}();\n }\n\n function withdrawDeposit(address payable withdrawAddress) public {\n entryPoint.withdrawStake(withdrawAddress);\n }\n}\n"
+ },
+ "contracts/samples/TestToken.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestToken is ERC20 {\n constructor ()\n ERC20(\"TST\", \"TestToken\") {\n }\n\n function mint(address sender, uint amount) external {\n _mint(sender, amount);\n }\n}\n"
+ },
+ "contracts/test/TestUtil.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"../UserOperation.sol\";\nimport \"../IWallet.sol\";\n\ncontract TestUtil {\n using UserOperationLib for UserOperation;\n\n function packUserOp(UserOperation calldata op) external pure returns (bytes memory){\n return op.pack();\n }\n\n function prefund(UserOperation calldata op) public view returns (uint) {\n return op.requiredPreFund(0);\n }\n\n}"
+ },
+ "contracts/test/TestCounter.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.7;\n\nimport \"../UserOperation.sol\";\nimport \"../IWallet.sol\";\n\n//sample \"receiver\" contract, for testing \"exec\" from wallet.\ncontract TestCounter {\n mapping(address => uint) public counters;\n\n function count() public {\n counters[msg.sender] = counters[msg.sender] + 1;\n\n }\n\n //helper method to waste gas\n // repeat - waste gas on writing storage in a loop\n // junk - dynamic buffer to stress the function size.\n mapping(uint => uint) xxx;\n uint offset;\n\n function gasWaster(uint repeat, string calldata /*junk*/) external {\n for (uint i = 1; i <= repeat; i++) {\n offset++;\n xxx[offset] = i;\n }\n }\n}"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 200
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata",
+ "devdoc",
+ "userdoc",
+ "storageLayout",
+ "evm.gasEstimates"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ },
+ "metadata": {
+ "useLiteralContent": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/.chainId
new file mode 100644
index 000000000..56a6051ca
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/.chainId
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/EntryPoint.json
new file mode 100644
index 000000000..037750fba
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 2,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/SimpleAccountFactory.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/SimpleAccountFactory.json
new file mode 100644
index 000000000..4559ec0ad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/SimpleAccountFactory.json
@@ -0,0 +1,107 @@
+{
+ "address": "0x9406Cc6185a346906296840746125a0E44976454",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "contract IEntryPoint",
+ "name": "_entryPoint",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "inputs": [],
+ "name": "accountImplementation",
+ "outputs": [
+ {
+ "internalType": "contract SimpleAccount",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "salt",
+ "type": "uint256"
+ }
+ ],
+ "name": "createAccount",
+ "outputs": [
+ {
+ "internalType": "contract SimpleAccount",
+ "name": "ret",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "salt",
+ "type": "uint256"
+ }
+ ],
+ "name": "getAddress",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ }
+ ],
+ "args": [
+ "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
+ ],
+ "numDeployments": 1,
+ "solcInputHash": "02113a2ed1850c3774563305ee607f11",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IEntryPoint\",\"name\":\"_entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"accountImplementation\",\"outputs\":[{\"internalType\":\"contract SimpleAccount\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"}],\"name\":\"createAccount\",\"outputs\":[{\"internalType\":\"contract SimpleAccount\",\"name\":\"ret\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"salt\",\"type\":\"uint256\"}],\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"createAccount(address,uint256)\":{\"notice\":\"create an account, and return its address. returns the address even if the account is already deployed. Note that during UserOperation execution, this method is called only if the account is not deployed. This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\"},\"getAddress(address,uint256)\":{\"notice\":\"calculate the counterfactual address of this account as it would be returned by createAccount()\"}},\"notice\":\"A sample factory contract for SimpleAccount A UserOperations \\\"initCode\\\" holds the address of the factory, and a method call (to createAccount, in this sample factory). The factory's createAccount returns the target account address even if it is already installed. This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/samples/SimpleAccountFactory.sol\":\"SimpleAccountFactory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x1d4afe6cb24200cc4545eed814ecf5847277dfe5d613a1707aad5fceecebcfff\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0xa2b22da3032e50b55f95ec1d13336102d675f341167aa76db571ef7f8bb7975d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(\\n Address.isContract(IBeacon(newBeacon).implementation()),\\n \\\"ERC1967: beacon implementation is not a contract\\\"\\n );\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xabf3f59bc0e5423eae45e459dbe92e7052c6983628d39008590edc852a62f94a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overridden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xc130fe33f1b2132158531a87734153293f6d07bc263ff4ac90e85da9c82c0e27\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n * @custom:oz-retyped-from bool\\n */\\n uint8 private _initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private _initializing;\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint8 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\\n * constructor.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n bool isTopLevelCall = !_initializing;\\n require(\\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n _initialized = 1;\\n if (isTopLevelCall) {\\n _initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n _initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: setting the version to 255 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint8 version) {\\n require(!_initializing && _initialized < version, \\\"Initializable: contract is already initialized\\\");\\n _initialized = version;\\n _initializing = true;\\n _;\\n _initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n require(_initializing, \\\"Initializable: contract is not initializing\\\");\\n _;\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n require(!_initializing, \\\"Initializable: contract is initializing\\\");\\n if (_initialized < type(uint8).max) {\\n _initialized = type(uint8).max;\\n emit Initialized(type(uint8).max);\\n }\\n }\\n\\n /**\\n * @dev Internal function that returns the initialized version. Returns `_initialized`\\n */\\n function _getInitializedVersion() internal view returns (uint8) {\\n return _initialized;\\n }\\n\\n /**\\n * @dev Internal function that returns the initialized version. Returns `_initializing`\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _initializing;\\n }\\n}\\n\",\"keccak256\":\"0xcee5467d5d873fb75dae6f98c01a8d25dd609f9d0374c7d39217bd5f9539a2d6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../ERC1967/ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\\n *\\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\\n * `UUPSUpgradeable` with a custom implementation of upgrades.\\n *\\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\\n *\\n * _Available since v4.1._\\n */\\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\\n address private immutable __self = address(this);\\n\\n /**\\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\\n * fail.\\n */\\n modifier onlyProxy() {\\n require(address(this) != __self, \\\"Function must be called through delegatecall\\\");\\n require(_getImplementation() == __self, \\\"Function must be called through active proxy\\\");\\n _;\\n }\\n\\n /**\\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\\n * callable on the implementing contract but not through proxies.\\n */\\n modifier notDelegated() {\\n require(address(this) == __self, \\\"UUPSUpgradeable: must not be called through delegatecall\\\");\\n _;\\n }\\n\\n /**\\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\\n */\\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\\n return _IMPLEMENTATION_SLOT;\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function upgradeTo(address newImplementation) external virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\\n * encoded in `data`.\\n *\\n * Calls {_authorizeUpgrade}.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\\n _authorizeUpgrade(newImplementation);\\n _upgradeToAndCallUUPS(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\\n * {upgradeTo} and {upgradeToAndCall}.\\n *\\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\\n *\\n * ```solidity\\n * function _authorizeUpgrade(address) internal override onlyOwner {}\\n * ```\\n */\\n function _authorizeUpgrade(address newImplementation) internal virtual;\\n}\\n\",\"keccak256\":\"0x85cc5aca68692044586dc5ca19a9868d3288f6b35d1085c620dd0278ed0abdaa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev _Available since v3.1._\\n */\\ninterface IERC1155Receiver is IERC165 {\\n /**\\n * @dev Handles the receipt of a single ERC1155 token type. This function is\\n * called at the end of a `safeTransferFrom` after the balance has been updated.\\n *\\n * NOTE: To accept the transfer, this must return\\n * `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))`\\n * (i.e. 0xf23a6e61, or its own function selector).\\n *\\n * @param operator The address which initiated the transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param id The ID of the token being transferred\\n * @param value The amount of tokens being transferred\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155Received(address,address,uint256,uint256,bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155Received(\\n address operator,\\n address from,\\n uint256 id,\\n uint256 value,\\n bytes calldata data\\n ) external returns (bytes4);\\n\\n /**\\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\\n * is called at the end of a `safeBatchTransferFrom` after the balances have\\n * been updated.\\n *\\n * NOTE: To accept the transfer(s), this must return\\n * `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))`\\n * (i.e. 0xbc197c81, or its own function selector).\\n *\\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\\n * @param from The address which previously owned the token\\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\\n * @param data Additional data with no specified format\\n * @return `bytes4(keccak256(\\\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\\\"))` if transfer is allowed\\n */\\n function onERC1155BatchReceived(\\n address operator,\\n address from,\\n uint256[] calldata ids,\\n uint256[] calldata values,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xeb373f1fdc7b755c6a750123a9b9e3a8a02c1470042fd6505d875000a80bde0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.\\n *\\n * Accounts can be notified of {IERC777} tokens being sent to them by having a\\n * contract implement this interface (contract holders can be their own\\n * implementer) and registering it on the\\n * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].\\n *\\n * See {IERC1820Registry} and {ERC1820Implementer}.\\n */\\ninterface IERC777Recipient {\\n /**\\n * @dev Called by an {IERC777} token contract whenever tokens are being\\n * moved or created into a registered account (`to`). The type of operation\\n * is conveyed by `from` being the zero address or not.\\n *\\n * This call occurs _after_ the token contract's state is updated, so\\n * {IERC777-balanceOf}, etc., can be used to query the post-operation state.\\n *\\n * This function may revert to prevent the operation from being executed.\\n */\\n function tokensReceived(\\n address operator,\\n address from,\\n address to,\\n uint256 amount,\\n bytes calldata userData,\\n bytes calldata operatorData\\n ) external;\\n}\\n\",\"keccak256\":\"0x1a5d61db2733202ba361e6d6741cd2e662380e22b80e987eacfc91973f2267dc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Create2.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(\\n uint256 amount,\\n bytes32 salt,\\n bytes memory bytecode\\n ) internal returns (address addr) {\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n /// @solidity memory-safe-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(\\n bytes32 salt,\\n bytes32 bytecodeHash,\\n address deployer\\n ) internal pure returns (address addr) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let ptr := mload(0x40) // Get free memory pointer\\n\\n // | | \\u2193 ptr ... \\u2193 ptr + 0x0B (start) ... \\u2193 ptr + 0x20 ... \\u2193 ptr + 0x40 ... |\\n // |-------------------|---------------------------------------------------------------------------|\\n // | bytecodeHash | CCCCCCCCCCCCC...CC |\\n // | salt | BBBBBBBBBBBBB...BB |\\n // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |\\n // | 0xFF | FF |\\n // |-------------------|---------------------------------------------------------------------------|\\n // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\\n // | keccak(start, 85) | \\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191\\u2191 |\\n\\n mstore(add(ptr, 0x40), bytecodeHash)\\n mstore(add(ptr, 0x20), salt)\\n mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes\\n let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff\\n mstore8(start, 0xff)\\n addr := keccak256(start, 85)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xafc07f37809f74d9c66d6461cc0f85fb5147ab855acd0acc30af4b2272130c61\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd5c50c54bf02740ebd122ff06832546cb5fa84486d52695a9ccfd11666e0c81d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV // Deprecated in v4.8\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n /// @solidity memory-safe-assembly\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address, RecoverError) {\\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\\n uint8 v = uint8((uint256(vs) >> 255) + 27);\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0xda898fa084aa1ddfdb346e6a40459e00a59d87071cce7c315a46d648dd71d0ba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"contracts/core/BaseAccount.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\n/* solhint-disable avoid-low-level-calls */\\n/* solhint-disable no-empty-blocks */\\n\\nimport \\\"../interfaces/IAccount.sol\\\";\\nimport \\\"../interfaces/IEntryPoint.sol\\\";\\nimport \\\"./Helpers.sol\\\";\\n\\n/**\\n * Basic account implementation.\\n * this contract provides the basic logic for implementing the IAccount interface - validateUserOp\\n * specific account implementation should inherit it and provide the account-specific logic\\n */\\nabstract contract BaseAccount is IAccount {\\n using UserOperationLib for UserOperation;\\n\\n //return value in case of signature failure, with no time-range.\\n // equivalent to _packValidationData(true,0,0);\\n uint256 constant internal SIG_VALIDATION_FAILED = 1;\\n\\n /**\\n * Return the account nonce.\\n * This method returns the next sequential nonce.\\n * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`\\n */\\n function getNonce() public view virtual returns (uint256) {\\n return entryPoint().getNonce(address(this), 0);\\n }\\n\\n /**\\n * return the entryPoint used by this account.\\n * subclass should return the current entryPoint used by this account.\\n */\\n function entryPoint() public view virtual returns (IEntryPoint);\\n\\n /**\\n * Validate user's signature and nonce.\\n * subclass doesn't need to override this method. Instead, it should override the specific internal validation methods.\\n */\\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\\n external override virtual returns (uint256 validationData) {\\n _requireFromEntryPoint();\\n validationData = _validateSignature(userOp, userOpHash);\\n _validateNonce(userOp.nonce);\\n _payPrefund(missingAccountFunds);\\n }\\n\\n /**\\n * ensure the request comes from the known entrypoint.\\n */\\n function _requireFromEntryPoint() internal virtual view {\\n require(msg.sender == address(entryPoint()), \\\"account: not from EntryPoint\\\");\\n }\\n\\n /**\\n * validate the signature is valid for this message.\\n * @param userOp validate the userOp.signature field\\n * @param userOpHash convenient field: the hash of the request, to check the signature against\\n * (also hashes the entrypoint and chain id)\\n * @return validationData signature and time-range of this operation\\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\\n * otherwise, an address of an \\\"authorizer\\\" contract.\\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \\\"indefinite\\\"\\n * <6-byte> validAfter - first timestamp this operation is valid\\n * If the account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\\n */\\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\\n internal virtual returns (uint256 validationData);\\n\\n /**\\n * Validate the nonce of the UserOperation.\\n * This method may validate the nonce requirement of this account.\\n * e.g.\\n * To limit the nonce to use sequenced UserOps only (no \\\"out of order\\\" UserOps):\\n * `require(nonce < type(uint64).max)`\\n * For a hypothetical account that *requires* the nonce to be out-of-order:\\n * `require(nonce & type(uint64).max == 0)`\\n *\\n * The actual nonce uniqueness is managed by the EntryPoint, and thus no other\\n * action is needed by the account itself.\\n *\\n * @param nonce to validate\\n *\\n * solhint-disable-next-line no-empty-blocks\\n */\\n function _validateNonce(uint256 nonce) internal view virtual {\\n }\\n\\n /**\\n * sends to the entrypoint (msg.sender) the missing funds for this transaction.\\n * subclass MAY override this method for better funds management\\n * (e.g. send to the entryPoint more than the minimum required, so that in future transactions\\n * it will not be required to send again)\\n * @param missingAccountFunds the minimum value this method should send the entrypoint.\\n * this value MAY be zero, in case there is enough deposit, or the userOp has a paymaster.\\n */\\n function _payPrefund(uint256 missingAccountFunds) internal virtual {\\n if (missingAccountFunds != 0) {\\n (bool success,) = payable(msg.sender).call{value : missingAccountFunds, gas : type(uint256).max}(\\\"\\\");\\n (success);\\n //ignore failure (its EntryPoint's job to verify, not account.)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5eb3253b32fd8ba8ae7b9d83da8e9924254a4d3d17a8772b41280e8572974b3c\",\"license\":\"GPL-3.0\"},\"contracts/core/Helpers.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\n/* solhint-disable no-inline-assembly */\\n\\n/**\\n * returned data from validateUserOp.\\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\\n * @param aggregator - address(0) - the account validated the signature by itself.\\n * address(1) - the account failed to validate the signature.\\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\\n * @param validAfter - this UserOp is valid only after this timestamp.\\n * @param validaUntil - this UserOp is valid only up to this timestamp.\\n */\\n struct ValidationData {\\n address aggregator;\\n uint48 validAfter;\\n uint48 validUntil;\\n }\\n\\n//extract sigFailed, validAfter, validUntil.\\n// also convert zero validUntil to type(uint48).max\\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\\n address aggregator = address(uint160(validationData));\\n uint48 validUntil = uint48(validationData >> 160);\\n if (validUntil == 0) {\\n validUntil = type(uint48).max;\\n }\\n uint48 validAfter = uint48(validationData >> (48 + 160));\\n return ValidationData(aggregator, validAfter, validUntil);\\n }\\n\\n// intersect account and paymaster ranges.\\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\\n ValidationData memory accountValidationData = _parseValidationData(validationData);\\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\\n address aggregator = accountValidationData.aggregator;\\n if (aggregator == address(0)) {\\n aggregator = pmValidationData.aggregator;\\n }\\n uint48 validAfter = accountValidationData.validAfter;\\n uint48 validUntil = accountValidationData.validUntil;\\n uint48 pmValidAfter = pmValidationData.validAfter;\\n uint48 pmValidUntil = pmValidationData.validUntil;\\n\\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\\n return ValidationData(aggregator, validAfter, validUntil);\\n }\\n\\n/**\\n * helper to pack the return value for validateUserOp\\n * @param data - the ValidationData to pack\\n */\\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\\n }\\n\\n/**\\n * helper to pack the return value for validateUserOp, when not using an aggregator\\n * @param sigFailed - true for signature failure, false for success\\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\\n * @param validAfter first timestamp this UserOperation is valid\\n */\\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\\n }\\n\\n/**\\n * keccak function over calldata.\\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\\n */\\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\\n assembly {\\n let mem := mload(0x40)\\n let len := data.length\\n calldatacopy(mem, data.offset, len)\\n ret := keccak256(mem, len)\\n }\\n }\\n\\n\",\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IAccount.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\ninterface IAccount {\\n\\n /**\\n * Validate user's signature and nonce\\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\\n * This allows making a \\\"simulation call\\\" without a valid signature\\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\\n *\\n * @dev Must validate caller is the entryPoint.\\n * Must validate the signature and nonce\\n * @param userOp the operation that is about to be executed.\\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\\n * The excess is left as a deposit in the entrypoint, for future calls.\\n * can be withdrawn anytime using \\\"entryPoint.withdrawTo()\\\"\\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\\n * otherwise, an address of an \\\"authorizer\\\" contract.\\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \\\"indefinite\\\"\\n * <6-byte> validAfter - first timestamp this operation is valid\\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\\n */\\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\\n external returns (uint256 validationData);\\n}\\n\",\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IAggregator.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\nimport \\\"./UserOperation.sol\\\";\\n\\n/**\\n * Aggregated Signatures validator.\\n */\\ninterface IAggregator {\\n\\n /**\\n * validate aggregated signature.\\n * revert if the aggregated signature does not match the given list of operations.\\n */\\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\\n\\n /**\\n * validate signature of a single userOp\\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\\n * @param userOp the userOperation received from the user.\\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\\n * (usually empty, unless account and aggregator support some kind of \\\"multisig\\\"\\n */\\n function validateUserOpSignature(UserOperation calldata userOp)\\n external view returns (bytes memory sigForUserOp);\\n\\n /**\\n * aggregate multiple signatures into a single value.\\n * This method is called off-chain to calculate the signature to pass with handleOps()\\n * bundler MAY use optimized custom code perform this aggregation\\n * @param userOps array of UserOperations to collect the signatures from.\\n * @return aggregatedSignature the aggregated signature\\n */\\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\\n}\\n\",\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IEntryPoint.sol\":{\"content\":\"/**\\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\\n ** Only one instance required on each chain.\\n **/\\n// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\n/* solhint-disable avoid-low-level-calls */\\n/* solhint-disable no-inline-assembly */\\n/* solhint-disable reason-string */\\n\\nimport \\\"./UserOperation.sol\\\";\\nimport \\\"./IStakeManager.sol\\\";\\nimport \\\"./IAggregator.sol\\\";\\nimport \\\"./INonceManager.sol\\\";\\n\\ninterface IEntryPoint is IStakeManager, INonceManager {\\n\\n /***\\n * An event emitted after each successful request\\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\\n * @param sender - the account that generates this request.\\n * @param paymaster - if non-null, the paymaster that pays for this request.\\n * @param nonce - the nonce value from the request.\\n * @param success - true if the sender transaction succeeded, false if reverted.\\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\\n */\\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\\n\\n /**\\n * account \\\"sender\\\" was deployed.\\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\\n * @param sender the account that is deployed\\n * @param factory the factory used to deploy this account (in the initCode)\\n * @param paymaster the paymaster used by this UserOp\\n */\\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\\n\\n /**\\n * An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\\n * @param userOpHash the request unique identifier.\\n * @param sender the sender of this request\\n * @param nonce the nonce used in the request\\n * @param revertReason - the return bytes from the (reverted) call to \\\"callData\\\".\\n */\\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\\n\\n /**\\n * an event emitted by handleOps(), before starting the execution loop.\\n * any event emitted before this event, is part of the validation.\\n */\\n event BeforeExecution();\\n\\n /**\\n * signature aggregator used by the following UserOperationEvents within this bundle.\\n */\\n event SignatureAggregatorChanged(address indexed aggregator);\\n\\n /**\\n * a custom revert error of handleOps, to identify the offending op.\\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\\n * @param reason - revert reason\\n * The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues,\\n * so a failure can be attributed to the correct entity.\\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\\n */\\n error FailedOp(uint256 opIndex, string reason);\\n\\n /**\\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\\n */\\n error SignatureValidationFailed(address aggregator);\\n\\n /**\\n * Successful result from simulateValidation.\\n * @param returnInfo gas and time-range returned values\\n * @param senderInfo stake information about the sender\\n * @param factoryInfo stake information about the factory (if any)\\n * @param paymasterInfo stake information about the paymaster (if any)\\n */\\n error ValidationResult(ReturnInfo returnInfo,\\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\\n\\n /**\\n * Successful result from simulateValidation, if the account returns a signature aggregator\\n * @param returnInfo gas and time-range returned values\\n * @param senderInfo stake information about the sender\\n * @param factoryInfo stake information about the factory (if any)\\n * @param paymasterInfo stake information about the paymaster (if any)\\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\\n * bundler MUST use it to verify the signature, or reject the UserOperation\\n */\\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\\n AggregatorStakeInfo aggregatorInfo);\\n\\n /**\\n * return value of getSenderAddress\\n */\\n error SenderAddressResult(address sender);\\n\\n /**\\n * return value of simulateHandleOp\\n */\\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\\n\\n //UserOps handled, per aggregator\\n struct UserOpsPerAggregator {\\n UserOperation[] userOps;\\n\\n // aggregator address\\n IAggregator aggregator;\\n // aggregated signature\\n bytes signature;\\n }\\n\\n /**\\n * Execute a batch of UserOperation.\\n * no signature aggregator is used.\\n * if any account requires an aggregator (that is, it returned an aggregator when\\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\\n * @param ops the operations to execute\\n * @param beneficiary the address to receive the fees\\n */\\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\\n\\n /**\\n * Execute a batch of UserOperation with Aggregators\\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\\n * @param beneficiary the address to receive the fees\\n */\\n function handleAggregatedOps(\\n UserOpsPerAggregator[] calldata opsPerAggregator,\\n address payable beneficiary\\n ) external;\\n\\n /**\\n * generate a request Id - unique identifier for this request.\\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\\n */\\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\\n\\n /**\\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\\n * @param userOp the user operation to validate.\\n */\\n function simulateValidation(UserOperation calldata userOp) external;\\n\\n /**\\n * gas and return values during simulation\\n * @param preOpGas the gas used for validation (including preValidationGas)\\n * @param prefund the required prefund for this operation\\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\\n */\\n struct ReturnInfo {\\n uint256 preOpGas;\\n uint256 prefund;\\n bool sigFailed;\\n uint48 validAfter;\\n uint48 validUntil;\\n bytes paymasterContext;\\n }\\n\\n /**\\n * returned aggregated signature info.\\n * the aggregator returned by the account, and its current stake.\\n */\\n struct AggregatorStakeInfo {\\n address aggregator;\\n StakeInfo stakeInfo;\\n }\\n\\n /**\\n * Get counterfactual sender address.\\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\\n * this method always revert, and returns the address in SenderAddressResult error\\n * @param initCode the constructor code to be passed into the UserOperation.\\n */\\n function getSenderAddress(bytes memory initCode) external;\\n\\n\\n /**\\n * simulate full execution of a UserOperation (including both validation and target execution)\\n * this method will always revert with \\\"ExecutionResult\\\".\\n * it performs full validation of the UserOperation, but ignores signature error.\\n * an optional target address is called after the userop succeeds, and its value is returned\\n * (before the entire call is reverted)\\n * Note that in order to collect the the success/failure of the target call, it must be executed\\n * with trace enabled to track the emitted events.\\n * @param op the UserOperation to simulate\\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\\n * are set to the return from that call.\\n * @param targetCallData callData to pass to target address\\n */\\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\\n}\\n\\n\",\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/INonceManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\ninterface INonceManager {\\n\\n /**\\n * Return the next nonce for this sender.\\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\\n * But UserOp with different keys can come with arbitrary order.\\n *\\n * @param sender the account address\\n * @param key the high 192 bit of the nonce\\n * @return nonce a full nonce to pass for next UserOp with this sender.\\n */\\n function getNonce(address sender, uint192 key)\\n external view returns (uint256 nonce);\\n\\n /**\\n * Manually increment the nonce of the sender.\\n * This method is exposed just for completeness..\\n * Account does NOT need to call it, neither during validation, nor elsewhere,\\n * as the EntryPoint will update the nonce regardless.\\n * Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future\\n * UserOperations will not pay extra for the first transaction with a given key.\\n */\\n function incrementNonce(uint192 key) external;\\n}\\n\",\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\"},\"contracts/interfaces/IStakeManager.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-only\\npragma solidity ^0.8.12;\\n\\n/**\\n * manage deposits and stakes.\\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\\n * stake is value locked for at least \\\"unstakeDelay\\\" by the staked entity.\\n */\\ninterface IStakeManager {\\n\\n event Deposited(\\n address indexed account,\\n uint256 totalDeposit\\n );\\n\\n event Withdrawn(\\n address indexed account,\\n address withdrawAddress,\\n uint256 amount\\n );\\n\\n /// Emitted when stake or unstake delay are modified\\n event StakeLocked(\\n address indexed account,\\n uint256 totalStaked,\\n uint256 unstakeDelaySec\\n );\\n\\n /// Emitted once a stake is scheduled for withdrawal\\n event StakeUnlocked(\\n address indexed account,\\n uint256 withdrawTime\\n );\\n\\n event StakeWithdrawn(\\n address indexed account,\\n address withdrawAddress,\\n uint256 amount\\n );\\n\\n /**\\n * @param deposit the entity's deposit\\n * @param staked true if this entity is staked.\\n * @param stake actual amount of ether staked for this entity.\\n * @param unstakeDelaySec minimum delay to withdraw the stake.\\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\\n * and the rest fit into a 2nd cell.\\n * 112 bit allows for 10^15 eth\\n * 48 bit for full timestamp\\n * 32 bit allows 150 years for unstake delay\\n */\\n struct DepositInfo {\\n uint112 deposit;\\n bool staked;\\n uint112 stake;\\n uint32 unstakeDelaySec;\\n uint48 withdrawTime;\\n }\\n\\n //API struct used by getStakeInfo and simulateValidation\\n struct StakeInfo {\\n uint256 stake;\\n uint256 unstakeDelaySec;\\n }\\n\\n /// @return info - full deposit information of given account\\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\\n\\n /// @return the deposit (for gas payment) of the account\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * add to the deposit of the given account\\n */\\n function depositTo(address account) external payable;\\n\\n /**\\n * add to the account's stake - amount and delay\\n * any pending unstake is first cancelled.\\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\\n */\\n function addStake(uint32 _unstakeDelaySec) external payable;\\n\\n /**\\n * attempt to unlock the stake.\\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\\n */\\n function unlockStake() external;\\n\\n /**\\n * withdraw from the (unlocked) stake.\\n * must first call unlockStake and wait for the unstakeDelay to pass\\n * @param withdrawAddress the address to send withdrawn value.\\n */\\n function withdrawStake(address payable withdrawAddress) external;\\n\\n /**\\n * withdraw from the deposit.\\n * @param withdrawAddress the address to send withdrawn value.\\n * @param withdrawAmount the amount to withdraw.\\n */\\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\\n}\\n\",\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\"},\"contracts/interfaces/UserOperation.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\n/* solhint-disable no-inline-assembly */\\n\\nimport {calldataKeccak} from \\\"../core/Helpers.sol\\\";\\n\\n/**\\n * User Operation struct\\n * @param sender the sender account of this request.\\n * @param nonce unique value the sender uses to verify it is not a replay.\\n * @param initCode if set, the account contract will be created by this constructor/\\n * @param callData the method call to execute on this account.\\n * @param callGasLimit the gas limit passed to the callData method call.\\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\\n * @param maxFeePerGas same as EIP-1559 gas parameter.\\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\\n */\\n struct UserOperation {\\n\\n address sender;\\n uint256 nonce;\\n bytes initCode;\\n bytes callData;\\n uint256 callGasLimit;\\n uint256 verificationGasLimit;\\n uint256 preVerificationGas;\\n uint256 maxFeePerGas;\\n uint256 maxPriorityFeePerGas;\\n bytes paymasterAndData;\\n bytes signature;\\n }\\n\\n/**\\n * Utility functions helpful when working with UserOperation structs.\\n */\\nlibrary UserOperationLib {\\n\\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\\n address data;\\n //read sender from userOp, which is first userOp member (saves 800 gas...)\\n assembly {data := calldataload(userOp)}\\n return address(uint160(data));\\n }\\n\\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\\n // pay above what he signed for.\\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\\n unchecked {\\n uint256 maxFeePerGas = userOp.maxFeePerGas;\\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\\n if (maxFeePerGas == maxPriorityFeePerGas) {\\n //legacy mode (for networks that don't support basefee opcode)\\n return maxFeePerGas;\\n }\\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\\n }\\n }\\n\\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\\n address sender = getSender(userOp);\\n uint256 nonce = userOp.nonce;\\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\\n bytes32 hashCallData = calldataKeccak(userOp.callData);\\n uint256 callGasLimit = userOp.callGasLimit;\\n uint256 verificationGasLimit = userOp.verificationGasLimit;\\n uint256 preVerificationGas = userOp.preVerificationGas;\\n uint256 maxFeePerGas = userOp.maxFeePerGas;\\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\\n\\n return abi.encode(\\n sender, nonce,\\n hashInitCode, hashCallData,\\n callGasLimit, verificationGasLimit, preVerificationGas,\\n maxFeePerGas, maxPriorityFeePerGas,\\n hashPaymasterAndData\\n );\\n }\\n\\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\\n return keccak256(pack(userOp));\\n }\\n\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\"},\"contracts/samples/SimpleAccount.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\n/* solhint-disable avoid-low-level-calls */\\n/* solhint-disable no-inline-assembly */\\n/* solhint-disable reason-string */\\n\\nimport \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/utils/Initializable.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\\\";\\n\\nimport \\\"../core/BaseAccount.sol\\\";\\nimport \\\"./callback/TokenCallbackHandler.sol\\\";\\n\\n/**\\n * minimal account.\\n * this is sample minimal account.\\n * has execute, eth handling methods\\n * has a single signer that can send requests through the entryPoint.\\n */\\ncontract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, Initializable {\\n using ECDSA for bytes32;\\n\\n address public owner;\\n\\n IEntryPoint private immutable _entryPoint;\\n\\n event SimpleAccountInitialized(IEntryPoint indexed entryPoint, address indexed owner);\\n\\n modifier onlyOwner() {\\n _onlyOwner();\\n _;\\n }\\n\\n /// @inheritdoc BaseAccount\\n function entryPoint() public view virtual override returns (IEntryPoint) {\\n return _entryPoint;\\n }\\n\\n\\n // solhint-disable-next-line no-empty-blocks\\n receive() external payable {}\\n\\n constructor(IEntryPoint anEntryPoint) {\\n _entryPoint = anEntryPoint;\\n _disableInitializers();\\n }\\n\\n function _onlyOwner() internal view {\\n //directly from EOA owner, or through the account itself (which gets redirected through execute())\\n require(msg.sender == owner || msg.sender == address(this), \\\"only owner\\\");\\n }\\n\\n /**\\n * execute a transaction (called directly from owner, or by entryPoint)\\n */\\n function execute(address dest, uint256 value, bytes calldata func) external {\\n _requireFromEntryPointOrOwner();\\n _call(dest, value, func);\\n }\\n\\n /**\\n * execute a sequence of transactions\\n */\\n function executeBatch(address[] calldata dest, bytes[] calldata func) external {\\n _requireFromEntryPointOrOwner();\\n require(dest.length == func.length, \\\"wrong array lengths\\\");\\n for (uint256 i = 0; i < dest.length; i++) {\\n _call(dest[i], 0, func[i]);\\n }\\n }\\n\\n /**\\n * @dev The _entryPoint member is immutable, to reduce gas consumption. To upgrade EntryPoint,\\n * a new implementation of SimpleAccount must be deployed with the new EntryPoint address, then upgrading\\n * the implementation by calling `upgradeTo()`\\n */\\n function initialize(address anOwner) public virtual initializer {\\n _initialize(anOwner);\\n }\\n\\n function _initialize(address anOwner) internal virtual {\\n owner = anOwner;\\n emit SimpleAccountInitialized(_entryPoint, owner);\\n }\\n\\n // Require the function call went through EntryPoint or owner\\n function _requireFromEntryPointOrOwner() internal view {\\n require(msg.sender == address(entryPoint()) || msg.sender == owner, \\\"account: not Owner or EntryPoint\\\");\\n }\\n\\n /// implement template method of BaseAccount\\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\\n internal override virtual returns (uint256 validationData) {\\n bytes32 hash = userOpHash.toEthSignedMessageHash();\\n if (owner != hash.recover(userOp.signature))\\n return SIG_VALIDATION_FAILED;\\n return 0;\\n }\\n\\n function _call(address target, uint256 value, bytes memory data) internal {\\n (bool success, bytes memory result) = target.call{value : value}(data);\\n if (!success) {\\n assembly {\\n revert(add(result, 32), mload(result))\\n }\\n }\\n }\\n\\n /**\\n * check current account deposit in the entryPoint\\n */\\n function getDeposit() public view returns (uint256) {\\n return entryPoint().balanceOf(address(this));\\n }\\n\\n /**\\n * deposit more funds for this account in the entryPoint\\n */\\n function addDeposit() public payable {\\n entryPoint().depositTo{value : msg.value}(address(this));\\n }\\n\\n /**\\n * withdraw value from the account's deposit\\n * @param withdrawAddress target to send to\\n * @param amount to withdraw\\n */\\n function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner {\\n entryPoint().withdrawTo(withdrawAddress, amount);\\n }\\n\\n function _authorizeUpgrade(address newImplementation) internal view override {\\n (newImplementation);\\n _onlyOwner();\\n }\\n}\\n\\n\",\"keccak256\":\"0x295bb73ecafb78a11e7418cc91d5f3c7f5fd5b2eba5e063d1e7d6bb6163192d4\",\"license\":\"GPL-3.0\"},\"contracts/samples/SimpleAccountFactory.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\nimport \\\"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\\\";\\n\\nimport \\\"./SimpleAccount.sol\\\";\\n\\n/**\\n * A sample factory contract for SimpleAccount\\n * A UserOperations \\\"initCode\\\" holds the address of the factory, and a method call (to createAccount, in this sample factory).\\n * The factory's createAccount returns the target account address even if it is already installed.\\n * This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.\\n */\\ncontract SimpleAccountFactory {\\n SimpleAccount public immutable accountImplementation;\\n\\n constructor(IEntryPoint _entryPoint) {\\n accountImplementation = new SimpleAccount(_entryPoint);\\n }\\n\\n /**\\n * create an account, and return its address.\\n * returns the address even if the account is already deployed.\\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\\n */\\n function createAccount(address owner,uint256 salt) public returns (SimpleAccount ret) {\\n address addr = getAddress(owner, salt);\\n uint codeSize = addr.code.length;\\n if (codeSize > 0) {\\n return SimpleAccount(payable(addr));\\n }\\n ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\\n address(accountImplementation),\\n abi.encodeCall(SimpleAccount.initialize, (owner))\\n )));\\n }\\n\\n /**\\n * calculate the counterfactual address of this account as it would be returned by createAccount()\\n */\\n function getAddress(address owner,uint256 salt) public view returns (address) {\\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\\n type(ERC1967Proxy).creationCode,\\n abi.encode(\\n address(accountImplementation),\\n abi.encodeCall(SimpleAccount.initialize, (owner))\\n )\\n )));\\n }\\n}\\n\",\"keccak256\":\"0xf2cb4f3889e79edb11aab8d8451e379691813fc6b945ca0b5c3a08017c27b5ed\",\"license\":\"GPL-3.0\"},\"contracts/samples/callback/TokenCallbackHandler.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.12;\\n\\n/* solhint-disable no-empty-blocks */\\n\\nimport \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\\\";\\n\\n/**\\n * Token callback handler.\\n * Handles supported tokens' callbacks, allowing account receiving these tokens.\\n */\\ncontract TokenCallbackHandler is IERC777Recipient, IERC721Receiver, IERC1155Receiver {\\n function tokensReceived(\\n address,\\n address,\\n address,\\n uint256,\\n bytes calldata,\\n bytes calldata\\n ) external pure override {\\n }\\n\\n function onERC721Received(\\n address,\\n address,\\n uint256,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n return IERC721Receiver.onERC721Received.selector;\\n }\\n\\n function onERC1155Received(\\n address,\\n address,\\n uint256,\\n uint256,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n return IERC1155Receiver.onERC1155Received.selector;\\n }\\n\\n function onERC1155BatchReceived(\\n address,\\n address,\\n uint256[] calldata,\\n uint256[] calldata,\\n bytes calldata\\n ) external pure override returns (bytes4) {\\n return IERC1155Receiver.onERC1155BatchReceived.selector;\\n }\\n\\n function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {\\n return\\n interfaceId == type(IERC721Receiver).interfaceId ||\\n interfaceId == type(IERC1155Receiver).interfaceId ||\\n interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xfff3df5f5211d71158bb017ff791dc4fa85db53890f7bd72bac3a43d89e83752\",\"license\":\"GPL-3.0\"}},\"version\":1}",
+ "bytecode": "0x60a060405234801561001057600080fd5b5060405161336238038061336283398101604081905261002f91610088565b8060405161003c9061007b565b6001600160a01b039091168152602001604051809103906000f080158015610068573d6000803e3d6000fd5b506001600160a01b0316608052506100b8565b6125dc80610d8683390190565b60006020828403121561009a57600080fd5b81516001600160a01b03811681146100b157600080fd5b9392505050565b608051610ca66100e060003960008181604b0152818161011401526102580152610ca66000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806311464fbe146100465780635fbfb9cf146100965780638cb84e18146100a9575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61006d6100a436600461039d565b6100bc565b61006d6100b736600461039d565b6101ee565b6000806100c984846101ee565b905073ffffffffffffffffffffffffffffffffffffffff81163b80156100f1575090506101e8565b60405173ffffffffffffffffffffffffffffffffffffffff8616602482015284907f000000000000000000000000000000000000000000000000000000000000000090604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de800000000000000000000000000000000000000000000000000000000179052516101b790610390565b6101c2929190610412565b8190604051809103906000f59050801580156101e2573d6000803e3d6000fd5b50925050505b92915050565b60006103578260001b6040518060200161020790610390565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081905273ffffffffffffffffffffffffffffffffffffffff871660248201527f000000000000000000000000000000000000000000000000000000000000000090604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de800000000000000000000000000000000000000000000000000000000179052905161030093929101610412565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261033c9291602001610480565b6040516020818303038152906040528051906020012061035e565b9392505050565b60006103578383306000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b6107c1806104b083390190565b600080604083850312156103b057600080fd5b823573ffffffffffffffffffffffffffffffffffffffff811681146103d457600080fd5b946020939093013593505050565b60005b838110156103fd5781810151838201526020016103e5565b8381111561040c576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000825180604084015261044d8160608501602087016103e2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b600083516104928184602088016103e2565b8351908301906104a68183602088016103e2565b0194935050505056fe60806040526040516107c13803806107c183398101604081905261002291610321565b61002e82826000610035565b505061043e565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161079a602791396101a9565b9392505050565b6100ea8161022260201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61023160201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080856001600160a01b0316856040516101c691906103ef565b600060405180830381855af49150503d8060008114610201576040519150601f19603f3d011682016040523d82523d6000602084013e610206565b606091505b50909250905061021886838387610234565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a357825160000361029c576001600160a01b0385163b61029c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610148565b50816102ad565b6102ad83836102b5565b949350505050565b8151156102c55781518083602001fd5b8060405162461bcd60e51b8152600401610148919061040b565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103105781810151838201526020016102f8565b838111156100645750506000910152565b6000806040838503121561033457600080fd5b82516001600160a01b038116811461034b57600080fd5b60208401519092506001600160401b038082111561036857600080fd5b818501915085601f83011261037c57600080fd5b81518181111561038e5761038e6102df565b604051601f8201601f19908116603f011681019083821181831017156103b6576103b66102df565b816040528281528860208487010111156103cf57600080fd5b6103e08360208301602088016102f5565b80955050505050509250929050565b600082516104018184602087016102f5565b9190910192915050565b602081526000825180602084015261042a8160408501602087016102f5565b601f01601f19169190910160400192915050565b61034d8061044d6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102f1602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516101079190610283565b600060405180830381855af49150503d8060008114610142576040519150601f19603f3d011682016040523d82523d6000602084013e610147565b606091505b509150915061015886838387610162565b9695505050505050565b606083156101fd5782516000036101f65773ffffffffffffffffffffffffffffffffffffffff85163b6101f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610207565b610207838361020f565b949350505050565b81511561021f5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ed919061029f565b60005b8381101561026e578181015183820152602001610256565b8381111561027d576000848401525b50505050565b60008251610295818460208701610253565b9190910192915050565b60208152600082518060208401526102be816040850160208701610253565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201cd78ab6a31213989661cff2d7d05fc9b9c38b1a848e8249e2e398659a9eb7e364736f6c634300080f0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122070aa03035a81441673770173c347020a4af1bf8f651ceebc066752c059bdbac764736f6c634300080f003360c0604052306080523480156200001557600080fd5b50604051620025dc380380620025dc833981016040819052620000389162000118565b6001600160a01b03811660a0526200004f62000056565b506200014a565b600054610100900460ff1615620000c35760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116101562000116576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6000602082840312156200012b57600080fd5b81516001600160a01b03811681146200014357600080fd5b9392505050565b60805160a05161241f620001bd6000396000818161032f015281816108810152818161092801528181610d4c01528181610f9d01528181610fe40152818161133601526115f501526000818161066b0152818161071b015281816109ec01528181610a9c0152610be5015261241f6000f3fe60806040526004361061012c5760003560e01c806352d1902d116100a5578063bc197c8111610074578063c4d66de811610059578063c4d66de8146103d0578063d087d288146103f0578063f23a6e611461040557600080fd5b8063bc197c8114610373578063c399ec88146103bb57600080fd5b806352d1902d146102b35780638da5cb5b146102c8578063b0d691fe14610320578063b61d27f61461035357600080fd5b80633659cfe6116100fc5780634a58db19116100e15780634a58db19146102785780634d44560d146102805780634f1ef286146102a057600080fd5b80633659cfe61461022a5780633a871cdd1461024a57600080fd5b806223de291461013857806301ffc9a71461015f578063150b7a021461019457806318dfb3c71461020a57600080fd5b3661013357005b600080fd5b34801561014457600080fd5b5061015d610153366004611cbf565b5050505050505050565b005b34801561016b57600080fd5b5061017f61017a366004611d70565b61044b565b60405190151581526020015b60405180910390f35b3480156101a057600080fd5b506101d96101af366004611db2565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200161018b565b34801561021657600080fd5b5061015d610225366004611e6a565b610530565b34801561023657600080fd5b5061015d610245366004611ed6565b610654565b34801561025657600080fd5b5061026a610265366004611ef3565b610859565b60405190815260200161018b565b61015d61087f565b34801561028c57600080fd5b5061015d61029b366004611f47565b61091e565b61015d6102ae366004611fa2565b6109d5565b3480156102bf57600080fd5b5061026a610bcb565b3480156102d457600080fd5b506000546102fb9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161018b565b34801561032c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102fb565b34801561035f57600080fd5b5061015d61036e366004612084565b610cb7565b34801561037f57600080fd5b506101d961038e3660046120d4565b7fbc197c810000000000000000000000000000000000000000000000000000000098975050505050505050565b3480156103c757600080fd5b5061026a610d06565b3480156103dc57600080fd5b5061015d6103eb366004611ed6565b610dbd565b3480156103fc57600080fd5b5061026a610f50565b34801561041157600080fd5b506101d9610420366004612172565b7ff23a6e61000000000000000000000000000000000000000000000000000000009695505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f150b7a020000000000000000000000000000000000000000000000000000000014806104de57507fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e000000000000000000000000000000000000000000000000000000000145b8061052a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b610538610fcc565b8281146105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f77726f6e67206172726179206c656e677468730000000000000000000000000060448201526064015b60405180910390fd5b60005b8381101561064d5761063b8585838181106105c6576105c66121ee565b90506020020160208101906105db9190611ed6565b60008585858181106105ef576105ef6121ee565b9050602002810190610601919061221d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061109592505050565b8061064581612282565b9150506105a9565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161059d565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1661078e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610831576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161059d565b61083a81611112565b604080516000808252602082019092526108569183919061111a565b50565b600061086361131e565b61086d84846113bd565b9050610878826114a3565b9392505050565b7f00000000000000000000000000000000000000000000000000000000000000006040517fb760faf900000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff919091169063b760faf99034906024016000604051808303818588803b15801561090a57600080fd5b505af115801561064d573d6000803e3d6000fd5b61092661150e565b7f00000000000000000000000000000000000000000000000000000000000000006040517f205c287800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015260248201849052919091169063205c287890604401600060405180830381600087803b1580156109b957600080fd5b505af11580156109cd573d6000803e3d6000fd5b505050505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c0000000000000000000000000000000000000000606482015260840161059d565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610b0f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f78790000000000000000000000000000000000000000606482015260840161059d565b610bbb82611112565b610bc78282600161111a565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610c92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161059d565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b610cbf610fcc565b610d00848484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061109592505050565b50505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a08231906024015b602060405180830381865afa158015610d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db891906122e1565b905090565b600054610100900460ff1615808015610ddd5750600054600160ff909116105b80610df75750303b158015610df7575060005460ff166001145b610e83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161059d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610ee157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610eea8261159f565b8015610bc757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6040517f35567e1a0000000000000000000000000000000000000000000000000000000081523060048201526000602482018190529073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906335567e1a90604401610d77565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148061102d575060005462010000900473ffffffffffffffffffffffffffffffffffffffff1633145b611093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f6163636f756e743a206e6f74204f776e6572206f7220456e747279506f696e74604482015260640161059d565b565b6000808473ffffffffffffffffffffffffffffffffffffffff1684846040516110be9190612326565b60006040518083038185875af1925050503d80600081146110fb576040519150601f19603f3d011682016040523d82523d6000602084013e611100565b606091505b50915091508161064d57805160208201fd5b61085661150e565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156111525761114d8361163e565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111d7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526111d4918101906122e1565b60015b611263576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f742055555053000000000000000000000000000000000000606482015260840161059d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611312576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c65555549440000000000000000000000000000000000000000000000606482015260840161059d565b5061114d838383611748565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f6163636f756e743a206e6f742066726f6d20456e747279506f696e7400000000604482015260640161059d565b600080611417836040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b905061146761142a61014086018661221d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250859392505061176d9050565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff90811691161461149957600191505061052a565b5060009392505050565b80156108565760405160009033907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90849084818181858888f193505050503d806000811461064d576040519150601f19603f3d011682016040523d82523d6000602084013e61064d565b60005462010000900473ffffffffffffffffffffffffffffffffffffffff1633148061153957503330145b611093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6f6e6c79206f776e657200000000000000000000000000000000000000000000604482015260640161059d565b600080547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8481168202929092178084556040519190048216927f0000000000000000000000000000000000000000000000000000000000000000909216917f47e55c76e7a6f1fd8996a1da8008c1ea29699cca35e7bcd057f2dec313b6e5de91a350565b73ffffffffffffffffffffffffffffffffffffffff81163b6116e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161059d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61175183611791565b60008251118061175e5750805b1561114d57610d0083836117de565b600080600061177c8585611803565b9150915061178981611848565b509392505050565b61179a8161163e565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061087883836040518060600160405280602781526020016123c3602791396119fb565b60008082516041036118395760208301516040840151606085015160001a61182d87828585611a80565b94509450505050611841565b506000905060025b9250929050565b600081600481111561185c5761185c612342565b036118645750565b600181600481111561187857611878612342565b036118df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161059d565b60028160048111156118f3576118f3612342565b0361195a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161059d565b600381600481111561196e5761196e612342565b03610856576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f7565000000000000000000000000000000000000000000000000000000000000606482015260840161059d565b60606000808573ffffffffffffffffffffffffffffffffffffffff1685604051611a259190612326565b600060405180830381855af49150503d8060008114611a60576040519150601f19603f3d011682016040523d82523d6000602084013e611a65565b606091505b5091509150611a7686838387611b6f565b9695505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611ab75750600090506003611b66565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611b0b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611b5f57600060019250925050611b66565b9150600090505b94509492505050565b60608315611c05578251600003611bfe5773ffffffffffffffffffffffffffffffffffffffff85163b611bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161059d565b5081611c0f565b611c0f8383611c17565b949350505050565b815115611c275781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059d9190612371565b73ffffffffffffffffffffffffffffffffffffffff8116811461085657600080fd5b60008083601f840112611c8f57600080fd5b50813567ffffffffffffffff811115611ca757600080fd5b60208301915083602082850101111561184157600080fd5b60008060008060008060008060c0898b031215611cdb57600080fd5b8835611ce681611c5b565b97506020890135611cf681611c5b565b96506040890135611d0681611c5b565b955060608901359450608089013567ffffffffffffffff80821115611d2a57600080fd5b611d368c838d01611c7d565b909650945060a08b0135915080821115611d4f57600080fd5b50611d5c8b828c01611c7d565b999c989b5096995094979396929594505050565b600060208284031215611d8257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461087857600080fd5b600080600080600060808688031215611dca57600080fd5b8535611dd581611c5b565b94506020860135611de581611c5b565b935060408601359250606086013567ffffffffffffffff811115611e0857600080fd5b611e1488828901611c7d565b969995985093965092949392505050565b60008083601f840112611e3757600080fd5b50813567ffffffffffffffff811115611e4f57600080fd5b6020830191508360208260051b850101111561184157600080fd5b60008060008060408587031215611e8057600080fd5b843567ffffffffffffffff80821115611e9857600080fd5b611ea488838901611e25565b90965094506020870135915080821115611ebd57600080fd5b50611eca87828801611e25565b95989497509550505050565b600060208284031215611ee857600080fd5b813561087881611c5b565b600080600060608486031215611f0857600080fd5b833567ffffffffffffffff811115611f1f57600080fd5b84016101608187031215611f3257600080fd5b95602085013595506040909401359392505050565b60008060408385031215611f5a57600080fd5b8235611f6581611c5b565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060408385031215611fb557600080fd5b8235611fc081611c5b565b9150602083013567ffffffffffffffff80821115611fdd57600080fd5b818501915085601f830112611ff157600080fd5b81358181111561200357612003611f73565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561204957612049611f73565b8160405282815288602084870101111561206257600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000806000806060858703121561209a57600080fd5b84356120a581611c5b565b935060208501359250604085013567ffffffffffffffff8111156120c857600080fd5b611eca87828801611c7d565b60008060008060008060008060a0898b0312156120f057600080fd5b88356120fb81611c5b565b9750602089013561210b81611c5b565b9650604089013567ffffffffffffffff8082111561212857600080fd5b6121348c838d01611e25565b909850965060608b013591508082111561214d57600080fd5b6121598c838d01611e25565b909650945060808b0135915080821115611d4f57600080fd5b60008060008060008060a0878903121561218b57600080fd5b863561219681611c5b565b955060208701356121a681611c5b565b94506040870135935060608701359250608087013567ffffffffffffffff8111156121d057600080fd5b6121dc89828a01611c7d565b979a9699509497509295939492505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261225257600080fd5b83018035915067ffffffffffffffff82111561226d57600080fd5b60200191503681900382131561184157600080fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036122da577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b6000602082840312156122f357600080fd5b5051919050565b60005b838110156123155781810151838201526020016122fd565b83811115610d005750506000910152565b600082516123388184602087016122fa565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208152600082518060208401526123908160408501602087016122fa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e7edcd8c7b9333c2bbdd5f8fa69f1cd2cb0f5cbfa76648b9830bcf0cbfef288e64736f6c634300080f0033",
+ "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806311464fbe146100465780635fbfb9cf146100965780638cb84e18146100a9575b600080fd5b61006d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61006d6100a436600461039d565b6100bc565b61006d6100b736600461039d565b6101ee565b6000806100c984846101ee565b905073ffffffffffffffffffffffffffffffffffffffff81163b80156100f1575090506101e8565b60405173ffffffffffffffffffffffffffffffffffffffff8616602482015284907f000000000000000000000000000000000000000000000000000000000000000090604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de800000000000000000000000000000000000000000000000000000000179052516101b790610390565b6101c2929190610412565b8190604051809103906000f59050801580156101e2573d6000803e3d6000fd5b50925050505b92915050565b60006103578260001b6040518060200161020790610390565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081905273ffffffffffffffffffffffffffffffffffffffff871660248201527f000000000000000000000000000000000000000000000000000000000000000090604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de800000000000000000000000000000000000000000000000000000000179052905161030093929101610412565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261033c9291602001610480565b6040516020818303038152906040528051906020012061035e565b9392505050565b60006103578383306000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b6107c1806104b083390190565b600080604083850312156103b057600080fd5b823573ffffffffffffffffffffffffffffffffffffffff811681146103d457600080fd5b946020939093013593505050565b60005b838110156103fd5781810151838201526020016103e5565b8381111561040c576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000825180604084015261044d8160608501602087016103e2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b600083516104928184602088016103e2565b8351908301906104a68183602088016103e2565b0194935050505056fe60806040526040516107c13803806107c183398101604081905261002291610321565b61002e82826000610035565b505061043e565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161079a602791396101a9565b9392505050565b6100ea8161022260201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61023160201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6060600080856001600160a01b0316856040516101c691906103ef565b600060405180830381855af49150503d8060008114610201576040519150601f19603f3d011682016040523d82523d6000602084013e610206565b606091505b50909250905061021886838387610234565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a357825160000361029c576001600160a01b0385163b61029c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610148565b50816102ad565b6102ad83836102b5565b949350505050565b8151156102c55781518083602001fd5b8060405162461bcd60e51b8152600401610148919061040b565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103105781810151838201526020016102f8565b838111156100645750506000910152565b6000806040838503121561033457600080fd5b82516001600160a01b038116811461034b57600080fd5b60208401519092506001600160401b038082111561036857600080fd5b818501915085601f83011261037c57600080fd5b81518181111561038e5761038e6102df565b604051601f8201601f19908116603f011681019083821181831017156103b6576103b66102df565b816040528281528860208487010111156103cf57600080fd5b6103e08360208301602088016102f5565b80955050505050509250929050565b600082516104018184602087016102f5565b9190910192915050565b602081526000825180602084015261042a8160408501602087016102f5565b601f01601f19169190910160400192915050565b61034d8061044d6000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102f1602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b60606000808573ffffffffffffffffffffffffffffffffffffffff16856040516101079190610283565b600060405180830381855af49150503d8060008114610142576040519150601f19603f3d011682016040523d82523d6000602084013e610147565b606091505b509150915061015886838387610162565b9695505050505050565b606083156101fd5782516000036101f65773ffffffffffffffffffffffffffffffffffffffff85163b6101f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b5081610207565b610207838361020f565b949350505050565b81511561021f5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101ed919061029f565b60005b8381101561026e578181015183820152602001610256565b8381111561027d576000848401525b50505050565b60008251610295818460208701610253565b9190910192915050565b60208152600082518060208401526102be816040850160208701610253565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212201cd78ab6a31213989661cff2d7d05fc9b9c38b1a848e8249e2e398659a9eb7e364736f6c634300080f0033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122070aa03035a81441673770173c347020a4af1bf8f651ceebc066752c059bdbac764736f6c634300080f0033",
+ "devdoc": {
+ "kind": "dev",
+ "methods": {},
+ "version": 1
+ },
+ "userdoc": {
+ "kind": "user",
+ "methods": {
+ "createAccount(address,uint256)": {
+ "notice": "create an account, and return its address. returns the address even if the account is already deployed. Note that during UserOperation execution, this method is called only if the account is not deployed. This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation"
+ },
+ "getAddress(address,uint256)": {
+ "notice": "calculate the counterfactual address of this account as it would be returned by createAccount()"
+ }
+ },
+ "notice": "A sample factory contract for SimpleAccount A UserOperations \"initCode\" holds the address of the factory, and a method call (to createAccount, in this sample factory). The factory's createAccount returns the target account address even if it is already installed. This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.",
+ "version": 1
+ },
+ "storageLayout": {
+ "storage": [],
+ "types": null
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/02113a2ed1850c3774563305ee607f11.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/02113a2ed1850c3774563305ee607f11.json
new file mode 100644
index 000000000..0df6e9575
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/02113a2ed1850c3774563305ee607f11.json
@@ -0,0 +1,329 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@gnosis.pm/safe-contracts/contracts/base/Executor.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\nimport \"../common/Enum.sol\";\n\n/// @title Executor - A contract that can execute transactions\n/// @author Richard Meissner - \ncontract Executor {\n function execute(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation,\n uint256 txGas\n ) internal returns (bool success) {\n if (operation == Enum.Operation.DelegateCall) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n } else {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/base/FallbackManager.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"../common/SelfAuthorized.sol\";\n\n/// @title Fallback Manager - A contract that manages fallback calls made to this contract\n/// @author Richard Meissner - \ncontract FallbackManager is SelfAuthorized {\n event ChangedFallbackHandler(address handler);\n\n // keccak256(\"fallback_manager.handler.address\")\n bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;\n\n function internalSetFallbackHandler(address handler) internal {\n bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, handler)\n }\n }\n\n /// @dev Allows to add a contract to handle fallback calls.\n /// Only fallback calls without value and with data will be forwarded.\n /// This can only be done via a Safe transaction.\n /// @param handler contract to handle fallbacks calls.\n function setFallbackHandler(address handler) public authorized {\n internalSetFallbackHandler(handler);\n emit ChangedFallbackHandler(handler);\n }\n\n // solhint-disable-next-line payable-fallback,no-complex-fallback\n fallback() external {\n bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let handler := sload(slot)\n if iszero(handler) {\n return(0, 0)\n }\n calldatacopy(0, 0, calldatasize())\n // The msg.sender address is shifted to the left by 12 bytes to remove the padding\n // Then the address without padding is stored right after the calldata\n mstore(calldatasize(), shl(96, caller()))\n // Add 20 bytes for the address appended add the end\n let success := call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0)\n returndatacopy(0, 0, returndatasize())\n if iszero(success) {\n revert(0, returndatasize())\n }\n return(0, returndatasize())\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/base/GuardManager.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"../common/Enum.sol\";\nimport \"../common/SelfAuthorized.sol\";\n\ninterface Guard {\n function checkTransaction(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation,\n uint256 safeTxGas,\n uint256 baseGas,\n uint256 gasPrice,\n address gasToken,\n address payable refundReceiver,\n bytes memory signatures,\n address msgSender\n ) external;\n\n function checkAfterExecution(bytes32 txHash, bool success) external;\n}\n\n/// @title Fallback Manager - A contract that manages fallback calls made to this contract\n/// @author Richard Meissner - \ncontract GuardManager is SelfAuthorized {\n event ChangedGuard(address guard);\n // keccak256(\"guard_manager.guard.address\")\n bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;\n\n /// @dev Set a guard that checks transactions before execution\n /// @param guard The address of the guard to be used or the 0 address to disable the guard\n function setGuard(address guard) external authorized {\n bytes32 slot = GUARD_STORAGE_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, guard)\n }\n emit ChangedGuard(guard);\n }\n\n function getGuard() internal view returns (address guard) {\n bytes32 slot = GUARD_STORAGE_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n guard := sload(slot)\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/base/ModuleManager.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\nimport \"../common/Enum.sol\";\nimport \"../common/SelfAuthorized.sol\";\nimport \"./Executor.sol\";\n\n/// @title Module Manager - A contract that manages modules that can execute transactions via this contract\n/// @author Stefan George - \n/// @author Richard Meissner - \ncontract ModuleManager is SelfAuthorized, Executor {\n event EnabledModule(address module);\n event DisabledModule(address module);\n event ExecutionFromModuleSuccess(address indexed module);\n event ExecutionFromModuleFailure(address indexed module);\n\n address internal constant SENTINEL_MODULES = address(0x1);\n\n mapping(address => address) internal modules;\n\n function setupModules(address to, bytes memory data) internal {\n require(modules[SENTINEL_MODULES] == address(0), \"GS100\");\n modules[SENTINEL_MODULES] = SENTINEL_MODULES;\n if (to != address(0))\n // Setup has to complete successfully or transaction fails.\n require(execute(to, 0, data, Enum.Operation.DelegateCall, gasleft()), \"GS000\");\n }\n\n /// @dev Allows to add a module to the whitelist.\n /// This can only be done via a Safe transaction.\n /// @notice Enables the module `module` for the Safe.\n /// @param module Module to be whitelisted.\n function enableModule(address module) public authorized {\n // Module address cannot be null or sentinel.\n require(module != address(0) && module != SENTINEL_MODULES, \"GS101\");\n // Module cannot be added twice.\n require(modules[module] == address(0), \"GS102\");\n modules[module] = modules[SENTINEL_MODULES];\n modules[SENTINEL_MODULES] = module;\n emit EnabledModule(module);\n }\n\n /// @dev Allows to remove a module from the whitelist.\n /// This can only be done via a Safe transaction.\n /// @notice Disables the module `module` for the Safe.\n /// @param prevModule Module that pointed to the module to be removed in the linked list\n /// @param module Module to be removed.\n function disableModule(address prevModule, address module) public authorized {\n // Validate module address and check that it corresponds to module index.\n require(module != address(0) && module != SENTINEL_MODULES, \"GS101\");\n require(modules[prevModule] == module, \"GS103\");\n modules[prevModule] = modules[module];\n modules[module] = address(0);\n emit DisabledModule(module);\n }\n\n /// @dev Allows a Module to execute a Safe transaction without any further confirmations.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction.\n function execTransactionFromModule(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) public virtual returns (bool success) {\n // Only whitelisted modules are allowed.\n require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), \"GS104\");\n // Execute transaction without further confirmations.\n success = execute(to, value, data, operation, gasleft());\n if (success) emit ExecutionFromModuleSuccess(msg.sender);\n else emit ExecutionFromModuleFailure(msg.sender);\n }\n\n /// @dev Allows a Module to execute a Safe transaction without any further confirmations and return data\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction.\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) public returns (bool success, bytes memory returnData) {\n success = execTransactionFromModule(to, value, data, operation);\n // solhint-disable-next-line no-inline-assembly\n assembly {\n // Load free memory location\n let ptr := mload(0x40)\n // We allocate memory for the return data by setting the free memory location to\n // current free memory location + data size + 32 bytes for data size value\n mstore(0x40, add(ptr, add(returndatasize(), 0x20)))\n // Store the size\n mstore(ptr, returndatasize())\n // Store the data\n returndatacopy(add(ptr, 0x20), 0, returndatasize())\n // Point the return data to the correct memory location\n returnData := ptr\n }\n }\n\n /// @dev Returns if an module is enabled\n /// @return True if the module is enabled\n function isModuleEnabled(address module) public view returns (bool) {\n return SENTINEL_MODULES != module && modules[module] != address(0);\n }\n\n /// @dev Returns array of modules.\n /// @param start Start of the page.\n /// @param pageSize Maximum number of modules that should be returned.\n /// @return array Array of modules.\n /// @return next Start of the next page.\n function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next) {\n // Init array with max page size\n array = new address[](pageSize);\n\n // Populate return array\n uint256 moduleCount = 0;\n address currentModule = modules[start];\n while (currentModule != address(0x0) && currentModule != SENTINEL_MODULES && moduleCount < pageSize) {\n array[moduleCount] = currentModule;\n currentModule = modules[currentModule];\n moduleCount++;\n }\n next = currentModule;\n // Set correct size of returned array\n // solhint-disable-next-line no-inline-assembly\n assembly {\n mstore(array, moduleCount)\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/base/OwnerManager.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\nimport \"../common/SelfAuthorized.sol\";\n\n/// @title OwnerManager - Manages a set of owners and a threshold to perform actions.\n/// @author Stefan George - \n/// @author Richard Meissner - \ncontract OwnerManager is SelfAuthorized {\n event AddedOwner(address owner);\n event RemovedOwner(address owner);\n event ChangedThreshold(uint256 threshold);\n\n address internal constant SENTINEL_OWNERS = address(0x1);\n\n mapping(address => address) internal owners;\n uint256 internal ownerCount;\n uint256 internal threshold;\n\n /// @dev Setup function sets initial storage of contract.\n /// @param _owners List of Safe owners.\n /// @param _threshold Number of required confirmations for a Safe transaction.\n function setupOwners(address[] memory _owners, uint256 _threshold) internal {\n // Threshold can only be 0 at initialization.\n // Check ensures that setup function can only be called once.\n require(threshold == 0, \"GS200\");\n // Validate that threshold is smaller than number of added owners.\n require(_threshold <= _owners.length, \"GS201\");\n // There has to be at least one Safe owner.\n require(_threshold >= 1, \"GS202\");\n // Initializing Safe owners.\n address currentOwner = SENTINEL_OWNERS;\n for (uint256 i = 0; i < _owners.length; i++) {\n // Owner address cannot be null.\n address owner = _owners[i];\n require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, \"GS203\");\n // No duplicate owners allowed.\n require(owners[owner] == address(0), \"GS204\");\n owners[currentOwner] = owner;\n currentOwner = owner;\n }\n owners[currentOwner] = SENTINEL_OWNERS;\n ownerCount = _owners.length;\n threshold = _threshold;\n }\n\n /// @dev Allows to add a new owner to the Safe and update the threshold at the same time.\n /// This can only be done via a Safe transaction.\n /// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.\n /// @param owner New owner address.\n /// @param _threshold New threshold.\n function addOwnerWithThreshold(address owner, uint256 _threshold) public authorized {\n // Owner address cannot be null, the sentinel or the Safe itself.\n require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), \"GS203\");\n // No duplicate owners allowed.\n require(owners[owner] == address(0), \"GS204\");\n owners[owner] = owners[SENTINEL_OWNERS];\n owners[SENTINEL_OWNERS] = owner;\n ownerCount++;\n emit AddedOwner(owner);\n // Change threshold if threshold was changed.\n if (threshold != _threshold) changeThreshold(_threshold);\n }\n\n /// @dev Allows to remove an owner from the Safe and update the threshold at the same time.\n /// This can only be done via a Safe transaction.\n /// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.\n /// @param prevOwner Owner that pointed to the owner to be removed in the linked list\n /// @param owner Owner address to be removed.\n /// @param _threshold New threshold.\n function removeOwner(\n address prevOwner,\n address owner,\n uint256 _threshold\n ) public authorized {\n // Only allow to remove an owner, if threshold can still be reached.\n require(ownerCount - 1 >= _threshold, \"GS201\");\n // Validate owner address and check that it corresponds to owner index.\n require(owner != address(0) && owner != SENTINEL_OWNERS, \"GS203\");\n require(owners[prevOwner] == owner, \"GS205\");\n owners[prevOwner] = owners[owner];\n owners[owner] = address(0);\n ownerCount--;\n emit RemovedOwner(owner);\n // Change threshold if threshold was changed.\n if (threshold != _threshold) changeThreshold(_threshold);\n }\n\n /// @dev Allows to swap/replace an owner from the Safe with another address.\n /// This can only be done via a Safe transaction.\n /// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.\n /// @param prevOwner Owner that pointed to the owner to be replaced in the linked list\n /// @param oldOwner Owner address to be replaced.\n /// @param newOwner New owner address.\n function swapOwner(\n address prevOwner,\n address oldOwner,\n address newOwner\n ) public authorized {\n // Owner address cannot be null, the sentinel or the Safe itself.\n require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), \"GS203\");\n // No duplicate owners allowed.\n require(owners[newOwner] == address(0), \"GS204\");\n // Validate oldOwner address and check that it corresponds to owner index.\n require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, \"GS203\");\n require(owners[prevOwner] == oldOwner, \"GS205\");\n owners[newOwner] = owners[oldOwner];\n owners[prevOwner] = newOwner;\n owners[oldOwner] = address(0);\n emit RemovedOwner(oldOwner);\n emit AddedOwner(newOwner);\n }\n\n /// @dev Allows to update the number of required confirmations by Safe owners.\n /// This can only be done via a Safe transaction.\n /// @notice Changes the threshold of the Safe to `_threshold`.\n /// @param _threshold New threshold.\n function changeThreshold(uint256 _threshold) public authorized {\n // Validate that threshold is smaller than number of owners.\n require(_threshold <= ownerCount, \"GS201\");\n // There has to be at least one Safe owner.\n require(_threshold >= 1, \"GS202\");\n threshold = _threshold;\n emit ChangedThreshold(threshold);\n }\n\n function getThreshold() public view returns (uint256) {\n return threshold;\n }\n\n function isOwner(address owner) public view returns (bool) {\n return owner != SENTINEL_OWNERS && owners[owner] != address(0);\n }\n\n /// @dev Returns array of owners.\n /// @return Array of Safe owners.\n function getOwners() public view returns (address[] memory) {\n address[] memory array = new address[](ownerCount);\n\n // populate return array\n uint256 index = 0;\n address currentOwner = owners[SENTINEL_OWNERS];\n while (currentOwner != SENTINEL_OWNERS) {\n array[index] = currentOwner;\n currentOwner = owners[currentOwner];\n index++;\n }\n return array;\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/Enum.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - \ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/EtherPaymentFallback.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title EtherPaymentFallback - A contract that has a fallback to accept ether payments\n/// @author Richard Meissner - \ncontract EtherPaymentFallback {\n event SafeReceived(address indexed sender, uint256 value);\n\n /// @dev Fallback function accepts Ether transactions.\n receive() external payable {\n emit SafeReceived(msg.sender, msg.value);\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/SecuredTokenTransfer.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title SecuredTokenTransfer - Secure token transfer\n/// @author Richard Meissner - \ncontract SecuredTokenTransfer {\n /// @dev Transfers a token and returns if it was a success\n /// @param token Token that should be transferred\n /// @param receiver Receiver to whom the token should be transferred\n /// @param amount The amount of tokens that should be transferred\n function transferToken(\n address token,\n address receiver,\n uint256 amount\n ) internal returns (bool transferred) {\n // 0xa9059cbb - keccack(\"transfer(address,uint256)\")\n bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount);\n // solhint-disable-next-line no-inline-assembly\n assembly {\n // We write the return value to scratch space.\n // See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory\n let success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20)\n switch returndatasize()\n case 0 {\n transferred := success\n }\n case 0x20 {\n transferred := iszero(or(iszero(success), iszero(mload(0))))\n }\n default {\n transferred := 0\n }\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/SelfAuthorized.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title SelfAuthorized - authorizes current contract to perform actions\n/// @author Richard Meissner - \ncontract SelfAuthorized {\n function requireSelfCall() private view {\n require(msg.sender == address(this), \"GS031\");\n }\n\n modifier authorized() {\n // This is a function call as it minimized the bytecode size\n requireSelfCall();\n _;\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/SignatureDecoder.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title SignatureDecoder - Decodes signatures that a encoded as bytes\n/// @author Richard Meissner - \ncontract SignatureDecoder {\n /// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.\n /// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures\n /// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access\n /// @param signatures concatenated rsv signatures\n function signatureSplit(bytes memory signatures, uint256 pos)\n internal\n pure\n returns (\n uint8 v,\n bytes32 r,\n bytes32 s\n )\n {\n // The signature format is a compact form of:\n // {bytes32 r}{bytes32 s}{uint8 v}\n // Compact means, uint8 is not padded to 32 bytes.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let signaturePos := mul(0x41, pos)\n r := mload(add(signatures, add(signaturePos, 0x20)))\n s := mload(add(signatures, add(signaturePos, 0x40)))\n // Here we are loading the last 32 bytes, including 31 bytes\n // of 's'. There is no 'mload8' to do this.\n //\n // 'byte' is not working due to the Solidity parser, so lets\n // use the second best option, 'and'\n v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/Singleton.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Singleton - Base for singleton contracts (should always be first super contract)\n/// This contract is tightly coupled to our proxy contract (see `proxies/GnosisSafeProxy.sol`)\n/// @author Richard Meissner - \ncontract Singleton {\n // singleton always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.\n // It should also always be ensured that the address is stored alone (uses a full word)\n address private singleton;\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/common/StorageAccessible.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title StorageAccessible - generic base contract that allows callers to access all internal storage.\n/// @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol\ncontract StorageAccessible {\n /**\n * @dev Reads `length` bytes of storage in the currents contract\n * @param offset - the offset in the current contract's storage in words to start reading from\n * @param length - the number of words (32 bytes) of data to read\n * @return the bytes that were read.\n */\n function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {\n bytes memory result = new bytes(length * 32);\n for (uint256 index = 0; index < length; index++) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let word := sload(add(offset, index))\n mstore(add(add(result, 0x20), mul(index, 0x20)), word)\n }\n }\n return result;\n }\n\n /**\n * @dev Performs a delegetecall on a targetContract in the context of self.\n * Internally reverts execution to avoid side effects (making it static).\n *\n * This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.\n * Specifically, the `returndata` after a call to this method will be:\n * `success:bool || response.length:uint256 || response:bytes`.\n *\n * @param targetContract Address of the contract containing the code to execute.\n * @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).\n */\n function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let success := delegatecall(gas(), targetContract, add(calldataPayload, 0x20), mload(calldataPayload), 0, 0)\n\n mstore(0x00, success)\n mstore(0x20, returndatasize())\n returndatacopy(0x40, 0, returndatasize())\n revert(0, add(returndatasize(), 0x40))\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/examples/libraries/GnosisSafeStorage.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title GnosisSafeStorage - Storage layout of the Safe contracts to be used in libraries\n/// @author Richard Meissner - \ncontract GnosisSafeStorage {\n // From /common/Singleton.sol\n address internal singleton;\n // From /common/ModuleManager.sol\n mapping(address => address) internal modules;\n // From /common/OwnerManager.sol\n mapping(address => address) internal owners;\n uint256 internal ownerCount;\n uint256 internal threshold;\n\n // From /GnosisSafe.sol\n bytes32 internal nonce;\n bytes32 internal domainSeparator;\n mapping(bytes32 => uint256) internal signedMessages;\n mapping(address => mapping(bytes32 => uint256)) internal approvedHashes;\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/external/GnosisSafeMath.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n * @title GnosisSafeMath\n * @dev Math operations with safety checks that revert on error\n * Renamed from SafeMath to GnosisSafeMath to avoid conflicts\n * TODO: remove once open zeppelin update to solc 0.5.0\n */\nlibrary GnosisSafeMath {\n /**\n * @dev Multiplies two numbers, reverts on overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b);\n\n return c;\n }\n\n /**\n * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Adds two numbers, reverts on overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n\n return c;\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"./base/ModuleManager.sol\";\nimport \"./base/OwnerManager.sol\";\nimport \"./base/FallbackManager.sol\";\nimport \"./base/GuardManager.sol\";\nimport \"./common/EtherPaymentFallback.sol\";\nimport \"./common/Singleton.sol\";\nimport \"./common/SignatureDecoder.sol\";\nimport \"./common/SecuredTokenTransfer.sol\";\nimport \"./common/StorageAccessible.sol\";\nimport \"./interfaces/ISignatureValidator.sol\";\nimport \"./external/GnosisSafeMath.sol\";\n\n/// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.\n/// @author Stefan George - \n/// @author Richard Meissner - \ncontract GnosisSafe is\n EtherPaymentFallback,\n Singleton,\n ModuleManager,\n OwnerManager,\n SignatureDecoder,\n SecuredTokenTransfer,\n ISignatureValidatorConstants,\n FallbackManager,\n StorageAccessible,\n GuardManager\n{\n using GnosisSafeMath for uint256;\n\n string public constant VERSION = \"1.3.0\";\n\n // keccak256(\n // \"EIP712Domain(uint256 chainId,address verifyingContract)\"\n // );\n bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;\n\n // keccak256(\n // \"SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)\"\n // );\n bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8;\n\n event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler);\n event ApproveHash(bytes32 indexed approvedHash, address indexed owner);\n event SignMsg(bytes32 indexed msgHash);\n event ExecutionFailure(bytes32 txHash, uint256 payment);\n event ExecutionSuccess(bytes32 txHash, uint256 payment);\n\n uint256 public nonce;\n bytes32 private _deprecatedDomainSeparator;\n // Mapping to keep track of all message hashes that have been approve by ALL REQUIRED owners\n mapping(bytes32 => uint256) public signedMessages;\n // Mapping to keep track of all hashes (message or transaction) that have been approve by ANY owners\n mapping(address => mapping(bytes32 => uint256)) public approvedHashes;\n\n // This constructor ensures that this contract can only be used as a master copy for Proxy contracts\n constructor() {\n // By setting the threshold it is not possible to call setup anymore,\n // so we create a Safe with 0 owners and threshold 1.\n // This is an unusable Safe, perfect for the singleton\n threshold = 1;\n }\n\n /// @dev Setup function sets initial storage of contract.\n /// @param _owners List of Safe owners.\n /// @param _threshold Number of required confirmations for a Safe transaction.\n /// @param to Contract address for optional delegate call.\n /// @param data Data payload for optional delegate call.\n /// @param fallbackHandler Handler for fallback calls to this contract\n /// @param paymentToken Token that should be used for the payment (0 is ETH)\n /// @param payment Value that should be paid\n /// @param paymentReceiver Adddress that should receive the payment (or 0 if tx.origin)\n function setup(\n address[] calldata _owners,\n uint256 _threshold,\n address to,\n bytes calldata data,\n address fallbackHandler,\n address paymentToken,\n uint256 payment,\n address payable paymentReceiver\n ) external {\n // setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice\n setupOwners(_owners, _threshold);\n if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler);\n // As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules\n setupModules(to, data);\n\n if (payment > 0) {\n // To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself)\n // baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment\n handlePayment(payment, 0, 1, paymentToken, paymentReceiver);\n }\n emit SafeSetup(msg.sender, _owners, _threshold, to, fallbackHandler);\n }\n\n /// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.\n /// Note: The fees are always transferred, even if the user transaction fails.\n /// @param to Destination address of Safe transaction.\n /// @param value Ether value of Safe transaction.\n /// @param data Data payload of Safe transaction.\n /// @param operation Operation type of Safe transaction.\n /// @param safeTxGas Gas that should be used for the Safe transaction.\n /// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)\n /// @param gasPrice Gas price that should be used for the payment calculation.\n /// @param gasToken Token address (or 0 if ETH) that is used for the payment.\n /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).\n /// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})\n function execTransaction(\n address to,\n uint256 value,\n bytes calldata data,\n Enum.Operation operation,\n uint256 safeTxGas,\n uint256 baseGas,\n uint256 gasPrice,\n address gasToken,\n address payable refundReceiver,\n bytes memory signatures\n ) public payable virtual returns (bool success) {\n bytes32 txHash;\n // Use scope here to limit variable lifetime and prevent `stack too deep` errors\n {\n bytes memory txHashData =\n encodeTransactionData(\n // Transaction info\n to,\n value,\n data,\n operation,\n safeTxGas,\n // Payment info\n baseGas,\n gasPrice,\n gasToken,\n refundReceiver,\n // Signature info\n nonce\n );\n // Increase nonce and execute transaction.\n nonce++;\n txHash = keccak256(txHashData);\n checkSignatures(txHash, txHashData, signatures);\n }\n address guard = getGuard();\n {\n if (guard != address(0)) {\n Guard(guard).checkTransaction(\n // Transaction info\n to,\n value,\n data,\n operation,\n safeTxGas,\n // Payment info\n baseGas,\n gasPrice,\n gasToken,\n refundReceiver,\n // Signature info\n signatures,\n msg.sender\n );\n }\n }\n // We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)\n // We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150\n require(gasleft() >= ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500, \"GS010\");\n // Use scope here to limit variable lifetime and prevent `stack too deep` errors\n {\n uint256 gasUsed = gasleft();\n // If the gasPrice is 0 we assume that nearly all available gas can be used (it is always more than safeTxGas)\n // We only substract 2500 (compared to the 3000 before) to ensure that the amount passed is still higher than safeTxGas\n success = execute(to, value, data, operation, gasPrice == 0 ? (gasleft() - 2500) : safeTxGas);\n gasUsed = gasUsed.sub(gasleft());\n // If no safeTxGas and no gasPrice was set (e.g. both are 0), then the internal tx is required to be successful\n // This makes it possible to use `estimateGas` without issues, as it searches for the minimum gas where the tx doesn't revert\n require(success || safeTxGas != 0 || gasPrice != 0, \"GS013\");\n // We transfer the calculated tx costs to the tx.origin to avoid sending it to intermediate contracts that have made calls\n uint256 payment = 0;\n if (gasPrice > 0) {\n payment = handlePayment(gasUsed, baseGas, gasPrice, gasToken, refundReceiver);\n }\n if (success) emit ExecutionSuccess(txHash, payment);\n else emit ExecutionFailure(txHash, payment);\n }\n {\n if (guard != address(0)) {\n Guard(guard).checkAfterExecution(txHash, success);\n }\n }\n }\n\n function handlePayment(\n uint256 gasUsed,\n uint256 baseGas,\n uint256 gasPrice,\n address gasToken,\n address payable refundReceiver\n ) private returns (uint256 payment) {\n // solhint-disable-next-line avoid-tx-origin\n address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;\n if (gasToken == address(0)) {\n // For ETH we will only adjust the gas price to not be higher than the actual used gas price\n payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice);\n require(receiver.send(payment), \"GS011\");\n } else {\n payment = gasUsed.add(baseGas).mul(gasPrice);\n require(transferToken(gasToken, receiver, payment), \"GS012\");\n }\n }\n\n /**\n * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.\n * @param dataHash Hash of the data (could be either a message hash or transaction hash)\n * @param data That should be signed (this is passed to an external validator contract)\n * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.\n */\n function checkSignatures(\n bytes32 dataHash,\n bytes memory data,\n bytes memory signatures\n ) public view {\n // Load threshold to avoid multiple storage loads\n uint256 _threshold = threshold;\n // Check that a threshold is set\n require(_threshold > 0, \"GS001\");\n checkNSignatures(dataHash, data, signatures, _threshold);\n }\n\n /**\n * @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.\n * @param dataHash Hash of the data (could be either a message hash or transaction hash)\n * @param data That should be signed (this is passed to an external validator contract)\n * @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.\n * @param requiredSignatures Amount of required valid signatures.\n */\n function checkNSignatures(\n bytes32 dataHash,\n bytes memory data,\n bytes memory signatures,\n uint256 requiredSignatures\n ) public view {\n // Check that the provided signature data is not too short\n require(signatures.length >= requiredSignatures.mul(65), \"GS020\");\n // There cannot be an owner with address 0.\n address lastOwner = address(0);\n address currentOwner;\n uint8 v;\n bytes32 r;\n bytes32 s;\n uint256 i;\n for (i = 0; i < requiredSignatures; i++) {\n (v, r, s) = signatureSplit(signatures, i);\n if (v == 0) {\n // If v is 0 then it is a contract signature\n // When handling contract signatures the address of the contract is encoded into r\n currentOwner = address(uint160(uint256(r)));\n\n // Check that signature data pointer (s) is not pointing inside the static part of the signatures bytes\n // This check is not completely accurate, since it is possible that more signatures than the threshold are send.\n // Here we only check that the pointer is not pointing inside the part that is being processed\n require(uint256(s) >= requiredSignatures.mul(65), \"GS021\");\n\n // Check that signature data pointer (s) is in bounds (points to the length of data -> 32 bytes)\n require(uint256(s).add(32) <= signatures.length, \"GS022\");\n\n // Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length\n uint256 contractSignatureLen;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSignatureLen := mload(add(add(signatures, s), 0x20))\n }\n require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, \"GS023\");\n\n // Check signature\n bytes memory contractSignature;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n // The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s\n contractSignature := add(add(signatures, s), 0x20)\n }\n require(ISignatureValidator(currentOwner).isValidSignature(data, contractSignature) == EIP1271_MAGIC_VALUE, \"GS024\");\n } else if (v == 1) {\n // If v is 1 then it is an approved hash\n // When handling approved hashes the address of the approver is encoded into r\n currentOwner = address(uint160(uint256(r)));\n // Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction\n require(msg.sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0, \"GS025\");\n } else if (v > 30) {\n // If v > 30 then default va (27,28) has been adjusted for eth_sign flow\n // To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover\n currentOwner = ecrecover(keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", dataHash)), v - 4, r, s);\n } else {\n // Default is the ecrecover flow with the provided data hash\n // Use ecrecover with the messageHash for EOA signatures\n currentOwner = ecrecover(dataHash, v, r, s);\n }\n require(currentOwner > lastOwner && owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, \"GS026\");\n lastOwner = currentOwner;\n }\n }\n\n /// @dev Allows to estimate a Safe transaction.\n /// This method is only meant for estimation purpose, therefore the call will always revert and encode the result in the revert data.\n /// Since the `estimateGas` function includes refunds, call this method to get an estimated of the costs that are deducted from the safe with `execTransaction`\n /// @param to Destination address of Safe transaction.\n /// @param value Ether value of Safe transaction.\n /// @param data Data payload of Safe transaction.\n /// @param operation Operation type of Safe transaction.\n /// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs).\n /// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version.\n function requiredTxGas(\n address to,\n uint256 value,\n bytes calldata data,\n Enum.Operation operation\n ) external returns (uint256) {\n uint256 startGas = gasleft();\n // We don't provide an error message here, as we use it to return the estimate\n require(execute(to, value, data, operation, gasleft()));\n uint256 requiredGas = startGas - gasleft();\n // Convert response to string and return via error message\n revert(string(abi.encodePacked(requiredGas)));\n }\n\n /**\n * @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.\n * @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.\n */\n function approveHash(bytes32 hashToApprove) external {\n require(owners[msg.sender] != address(0), \"GS030\");\n approvedHashes[msg.sender][hashToApprove] = 1;\n emit ApproveHash(hashToApprove, msg.sender);\n }\n\n /// @dev Returns the chain id used by this contract.\n function getChainId() public view returns (uint256) {\n uint256 id;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n id := chainid()\n }\n return id;\n }\n\n function domainSeparator() public view returns (bytes32) {\n return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this));\n }\n\n /// @dev Returns the bytes that are hashed to be signed by owners.\n /// @param to Destination address.\n /// @param value Ether value.\n /// @param data Data payload.\n /// @param operation Operation type.\n /// @param safeTxGas Gas that should be used for the safe transaction.\n /// @param baseGas Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)\n /// @param gasPrice Maximum gas price that should be used for this transaction.\n /// @param gasToken Token address (or 0 if ETH) that is used for the payment.\n /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).\n /// @param _nonce Transaction nonce.\n /// @return Transaction hash bytes.\n function encodeTransactionData(\n address to,\n uint256 value,\n bytes calldata data,\n Enum.Operation operation,\n uint256 safeTxGas,\n uint256 baseGas,\n uint256 gasPrice,\n address gasToken,\n address refundReceiver,\n uint256 _nonce\n ) public view returns (bytes memory) {\n bytes32 safeTxHash =\n keccak256(\n abi.encode(\n SAFE_TX_TYPEHASH,\n to,\n value,\n keccak256(data),\n operation,\n safeTxGas,\n baseGas,\n gasPrice,\n gasToken,\n refundReceiver,\n _nonce\n )\n );\n return abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator(), safeTxHash);\n }\n\n /// @dev Returns hash to be signed by owners.\n /// @param to Destination address.\n /// @param value Ether value.\n /// @param data Data payload.\n /// @param operation Operation type.\n /// @param safeTxGas Fas that should be used for the safe transaction.\n /// @param baseGas Gas costs for data used to trigger the safe transaction.\n /// @param gasPrice Maximum gas price that should be used for this transaction.\n /// @param gasToken Token address (or 0 if ETH) that is used for the payment.\n /// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).\n /// @param _nonce Transaction nonce.\n /// @return Transaction hash.\n function getTransactionHash(\n address to,\n uint256 value,\n bytes calldata data,\n Enum.Operation operation,\n uint256 safeTxGas,\n uint256 baseGas,\n uint256 gasPrice,\n address gasToken,\n address refundReceiver,\n uint256 _nonce\n ) public view returns (bytes32) {\n return keccak256(encodeTransactionData(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce));\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/handler/DefaultCallbackHandler.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"../interfaces/ERC1155TokenReceiver.sol\";\nimport \"../interfaces/ERC721TokenReceiver.sol\";\nimport \"../interfaces/ERC777TokensRecipient.sol\";\nimport \"../interfaces/IERC165.sol\";\n\n/// @title Default Callback Handler - returns true for known token callbacks\n/// @author Richard Meissner - \ncontract DefaultCallbackHandler is ERC1155TokenReceiver, ERC777TokensRecipient, ERC721TokenReceiver, IERC165 {\n string public constant NAME = \"Default Callback Handler\";\n string public constant VERSION = \"1.0.0\";\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n ) external pure override returns (bytes4) {\n return 0xf23a6e61;\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata,\n uint256[] calldata,\n bytes calldata\n ) external pure override returns (bytes4) {\n return 0xbc197c81;\n }\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (bytes4) {\n return 0x150b7a02;\n }\n\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n ) external pure override {\n // We implement this for completeness, doesn't really have any value\n }\n\n function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {\n return\n interfaceId == type(ERC1155TokenReceiver).interfaceId ||\n interfaceId == type(ERC721TokenReceiver).interfaceId ||\n interfaceId == type(IERC165).interfaceId;\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/interfaces/ERC1155TokenReceiver.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/**\n Note: The ERC-165 identifier for this interface is 0x4e2312e0.\n*/\ninterface ERC1155TokenReceiver {\n /**\n @notice Handle the receipt of a single ERC1155 token type.\n @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated. \n This function MUST return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` (i.e. 0xf23a6e61) if it accepts the transfer.\n This function MUST revert if it rejects the transfer.\n Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.\n @param _operator The address which initiated the transfer (i.e. msg.sender)\n @param _from The address which previously owned the token\n @param _id The ID of the token being transferred\n @param _value The amount of tokens being transferred\n @param _data Additional data with no specified format\n @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n */\n function onERC1155Received(\n address _operator,\n address _from,\n uint256 _id,\n uint256 _value,\n bytes calldata _data\n ) external returns (bytes4);\n\n /**\n @notice Handle the receipt of multiple ERC1155 token types.\n @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated. \n This function MUST return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` (i.e. 0xbc197c81) if it accepts the transfer(s).\n This function MUST revert if it rejects the transfer(s).\n Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.\n @param _operator The address which initiated the batch transfer (i.e. msg.sender)\n @param _from The address which previously owned the token\n @param _ids An array containing ids of each token being transferred (order and length must match _values array)\n @param _values An array containing amounts of each token being transferred (order and length must match _ids array)\n @param _data Additional data with no specified format\n @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n */\n function onERC1155BatchReceived(\n address _operator,\n address _from,\n uint256[] calldata _ids,\n uint256[] calldata _values,\n bytes calldata _data\n ) external returns (bytes4);\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/interfaces/ERC721TokenReceiver.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.\ninterface ERC721TokenReceiver {\n /// @notice Handle the receipt of an NFT\n /// @dev The ERC721 smart contract calls this function on the recipient\n /// after a `transfer`. This function MAY throw to revert and reject the\n /// transfer. Return of other than the magic value MUST result in the\n /// transaction being reverted.\n /// Note: the contract address is always the message sender.\n /// @param _operator The address which called `safeTransferFrom` function\n /// @param _from The address which previously owned the token\n /// @param _tokenId The NFT identifier which is being transferred\n /// @param _data Additional data with no specified format\n /// @return `bytes4(keccak256(\"onERC721Received(address,address,uint256,bytes)\"))`\n /// unless throwing\n function onERC721Received(\n address _operator,\n address _from,\n uint256 _tokenId,\n bytes calldata _data\n ) external returns (bytes4);\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/interfaces/ERC777TokensRecipient.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\ninterface ERC777TokensRecipient {\n function tokensReceived(\n address operator,\n address from,\n address to,\n uint256 amount,\n bytes calldata data,\n bytes calldata operatorData\n ) external;\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/interfaces/IERC165.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @notice More details at https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/interfaces/ISignatureValidator.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\ncontract ISignatureValidatorConstants {\n // bytes4(keccak256(\"isValidSignature(bytes,bytes)\")\n bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;\n}\n\nabstract contract ISignatureValidator is ISignatureValidatorConstants {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param _data Arbitrary length data signed on the behalf of address(this)\n * @param _signature Signature byte array associated with _data\n *\n * MUST return the bytes4 magic value 0x20c13b0b when function passes.\n * MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)\n * MUST allow external calls\n */\n function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxy.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title IProxy - Helper interface to access masterCopy of the Proxy on-chain\n/// @author Richard Meissner - \ninterface IProxy {\n function masterCopy() external view returns (address);\n}\n\n/// @title GnosisSafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.\n/// @author Stefan George - \n/// @author Richard Meissner - \ncontract GnosisSafeProxy {\n // singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.\n // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`\n address internal singleton;\n\n /// @dev Constructor function sets address of singleton contract.\n /// @param _singleton Singleton address.\n constructor(address _singleton) {\n require(_singleton != address(0), \"Invalid singleton address provided\");\n singleton = _singleton;\n }\n\n /// @dev Fallback function forwards all transactions and returns all received return data.\n fallback() external payable {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let _singleton := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)\n // 0xa619486e == keccak(\"masterCopy()\"). The value is right padded to 32-bytes with 0s\n if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {\n mstore(0, _singleton)\n return(0, 0x20)\n }\n calldatacopy(0, 0, calldatasize())\n let success := delegatecall(gas(), _singleton, 0, calldatasize(), 0, 0)\n returndatacopy(0, 0, returndatasize())\n if eq(success, 0) {\n revert(0, returndatasize())\n }\n return(0, returndatasize())\n }\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"./GnosisSafeProxy.sol\";\nimport \"./IProxyCreationCallback.sol\";\n\n/// @title Proxy Factory - Allows to create new proxy contact and execute a message call to the new proxy within one transaction.\n/// @author Stefan George - \ncontract GnosisSafeProxyFactory {\n event ProxyCreation(GnosisSafeProxy proxy, address singleton);\n\n /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.\n /// @param singleton Address of singleton contract.\n /// @param data Payload for message call sent to new proxy contract.\n function createProxy(address singleton, bytes memory data) public returns (GnosisSafeProxy proxy) {\n proxy = new GnosisSafeProxy(singleton);\n if (data.length > 0)\n // solhint-disable-next-line no-inline-assembly\n assembly {\n if eq(call(gas(), proxy, 0, add(data, 0x20), mload(data), 0, 0), 0) {\n revert(0, 0)\n }\n }\n emit ProxyCreation(proxy, singleton);\n }\n\n /// @dev Allows to retrieve the runtime code of a deployed Proxy. This can be used to check that the expected Proxy was deployed.\n function proxyRuntimeCode() public pure returns (bytes memory) {\n return type(GnosisSafeProxy).runtimeCode;\n }\n\n /// @dev Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address.\n function proxyCreationCode() public pure returns (bytes memory) {\n return type(GnosisSafeProxy).creationCode;\n }\n\n /// @dev Allows to create new proxy contact using CREATE2 but it doesn't run the initializer.\n /// This method is only meant as an utility to be called from other methods\n /// @param _singleton Address of singleton contract.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\n function deployProxyWithNonce(\n address _singleton,\n bytes memory initializer,\n uint256 saltNonce\n ) internal returns (GnosisSafeProxy proxy) {\n // If the initializer changes the proxy address should change too. Hashing the initializer data is cheaper than just concatinating it\n bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));\n bytes memory deploymentData = abi.encodePacked(type(GnosisSafeProxy).creationCode, uint256(uint160(_singleton)));\n // solhint-disable-next-line no-inline-assembly\n assembly {\n proxy := create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt)\n }\n require(address(proxy) != address(0), \"Create2 call failed\");\n }\n\n /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.\n /// @param _singleton Address of singleton contract.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\n function createProxyWithNonce(\n address _singleton,\n bytes memory initializer,\n uint256 saltNonce\n ) public returns (GnosisSafeProxy proxy) {\n proxy = deployProxyWithNonce(_singleton, initializer, saltNonce);\n if (initializer.length > 0)\n // solhint-disable-next-line no-inline-assembly\n assembly {\n if eq(call(gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0), 0) {\n revert(0, 0)\n }\n }\n emit ProxyCreation(proxy, _singleton);\n }\n\n /// @dev Allows to create new proxy contact, execute a message call to the new proxy and call a specified callback within one transaction\n /// @param _singleton Address of singleton contract.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\n /// @param callback Callback that will be invoced after the new proxy contract has been successfully deployed and initialized.\n function createProxyWithCallback(\n address _singleton,\n bytes memory initializer,\n uint256 saltNonce,\n IProxyCreationCallback callback\n ) public returns (GnosisSafeProxy proxy) {\n uint256 saltNonceWithCallback = uint256(keccak256(abi.encodePacked(saltNonce, callback)));\n proxy = createProxyWithNonce(_singleton, initializer, saltNonceWithCallback);\n if (address(callback) != address(0)) callback.proxyCreated(proxy, _singleton, initializer, saltNonce);\n }\n\n /// @dev Allows to get the address for a new proxy contact created via `createProxyWithNonce`\n /// This method is only meant for address calculation purpose when you use an initializer that would revert,\n /// therefore the response is returned with a revert. When calling this method set `from` to the address of the proxy factory.\n /// @param _singleton Address of singleton contract.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.\n function calculateCreateProxyWithNonceAddress(\n address _singleton,\n bytes calldata initializer,\n uint256 saltNonce\n ) external returns (GnosisSafeProxy proxy) {\n proxy = deployProxyWithNonce(_singleton, initializer, saltNonce);\n revert(string(abi.encodePacked(proxy)));\n }\n}\n"
+ },
+ "@gnosis.pm/safe-contracts/contracts/proxies/IProxyCreationCallback.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\nimport \"./GnosisSafeProxy.sol\";\n\ninterface IProxyCreationCallback {\n function proxyCreated(\n GnosisSafeProxy proxy,\n address _singleton,\n bytes calldata initializer,\n uint256 saltNonce\n ) external;\n}\n"
+ },
+ "@openzeppelin/contracts/access/Ownable.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n"
+ },
+ "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n"
+ },
+ "@openzeppelin/contracts/interfaces/IERC1271.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param hash Hash of the data to be signed\n * @param signature Signature byte array associated with _data\n */\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n"
+ },
+ "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n"
+ },
+ "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n"
+ },
+ "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n"
+ },
+ "@openzeppelin/contracts/proxy/Proxy.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n"
+ },
+ "@openzeppelin/contracts/proxy/utils/Initializable.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Internal function that returns the initialized version. Returns `_initialized`\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Internal function that returns the initialized version. Returns `_initializing`\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n"
+ },
+ "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n}\n"
+ },
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n"
+ },
+ "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC777/IERC777Recipient.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC777TokensRecipient standard as defined in the EIP.\n *\n * Accounts can be notified of {IERC777} tokens being sent to them by having a\n * contract implement this interface (contract holders can be their own\n * implementer) and registering it on the\n * https://eips.ethereum.org/EIPS/eip-1820[ERC1820 global registry].\n *\n * See {IERC1820Registry} and {ERC1820Implementer}.\n */\ninterface IERC777Recipient {\n /**\n * @dev Called by an {IERC777} token contract whenever tokens are being\n * moved or created into a registered account (`to`). The type of operation\n * is conveyed by `from` being the zero address or not.\n *\n * This call occurs _after_ the token contract's state is updated, so\n * {IERC777-balanceOf}, etc., can be used to query the post-operation state.\n *\n * This function may revert to prevent the operation from being executed.\n */\n function tokensReceived(\n address operator,\n address from,\n address to,\n uint256 amount,\n bytes calldata userData,\n bytes calldata operatorData\n ) external;\n}\n"
+ },
+ "@openzeppelin/contracts/utils/Address.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/Context.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/Create2.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Create2.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(\n uint256 amount,\n bytes32 salt,\n bytes memory bytecode\n ) internal returns (address addr) {\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n /// @solidity memory-safe-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(\n bytes32 salt,\n bytes32 bytecodeHash,\n address deployer\n ) internal pure returns (address addr) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40) // Get free memory pointer\n\n // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |\n // |-------------------|---------------------------------------------------------------------------|\n // | bytecodeHash | CCCCCCCCCCCCC...CC |\n // | salt | BBBBBBBBBBBBB...BB |\n // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |\n // | 0xFF | FF |\n // |-------------------|---------------------------------------------------------------------------|\n // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\n // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |\n\n mstore(add(ptr, 0x40), bytecodeHash)\n mstore(add(ptr, 0x20), salt)\n mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes\n let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff\n mstore8(start, 0xff)\n addr := keccak256(start, 85)\n }\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
+ },
+ "@openzeppelin/contracts/utils/math/Math.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/StorageSlot.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n"
+ },
+ "@openzeppelin/contracts/utils/Strings.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n"
+ },
+ "contracts/core/BaseAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-empty-blocks */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"./Helpers.sol\";\n\n/**\n * Basic account implementation.\n * this contract provides the basic logic for implementing the IAccount interface - validateUserOp\n * specific account implementation should inherit it and provide the account-specific logic\n */\nabstract contract BaseAccount is IAccount {\n using UserOperationLib for UserOperation;\n\n //return value in case of signature failure, with no time-range.\n // equivalent to _packValidationData(true,0,0);\n uint256 constant internal SIG_VALIDATION_FAILED = 1;\n\n /**\n * Return the account nonce.\n * This method returns the next sequential nonce.\n * For a nonce of a specific key, use `entrypoint.getNonce(account, key)`\n */\n function getNonce() public view virtual returns (uint256) {\n return entryPoint().getNonce(address(this), 0);\n }\n\n /**\n * return the entryPoint used by this account.\n * subclass should return the current entryPoint used by this account.\n */\n function entryPoint() public view virtual returns (IEntryPoint);\n\n /**\n * Validate user's signature and nonce.\n * subclass doesn't need to override this method. Instead, it should override the specific internal validation methods.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external override virtual returns (uint256 validationData) {\n _requireFromEntryPoint();\n validationData = _validateSignature(userOp, userOpHash);\n _validateNonce(userOp.nonce);\n _payPrefund(missingAccountFunds);\n }\n\n /**\n * ensure the request comes from the known entrypoint.\n */\n function _requireFromEntryPoint() internal virtual view {\n require(msg.sender == address(entryPoint()), \"account: not from EntryPoint\");\n }\n\n /**\n * validate the signature is valid for this message.\n * @param userOp validate the userOp.signature field\n * @param userOpHash convenient field: the hash of the request, to check the signature against\n * (also hashes the entrypoint and chain id)\n * @return validationData signature and time-range of this operation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If the account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\n internal virtual returns (uint256 validationData);\n\n /**\n * Validate the nonce of the UserOperation.\n * This method may validate the nonce requirement of this account.\n * e.g.\n * To limit the nonce to use sequenced UserOps only (no \"out of order\" UserOps):\n * `require(nonce < type(uint64).max)`\n * For a hypothetical account that *requires* the nonce to be out-of-order:\n * `require(nonce & type(uint64).max == 0)`\n *\n * The actual nonce uniqueness is managed by the EntryPoint, and thus no other\n * action is needed by the account itself.\n *\n * @param nonce to validate\n *\n * solhint-disable-next-line no-empty-blocks\n */\n function _validateNonce(uint256 nonce) internal view virtual {\n }\n\n /**\n * sends to the entrypoint (msg.sender) the missing funds for this transaction.\n * subclass MAY override this method for better funds management\n * (e.g. send to the entryPoint more than the minimum required, so that in future transactions\n * it will not be required to send again)\n * @param missingAccountFunds the minimum value this method should send the entrypoint.\n * this value MAY be zero, in case there is enough deposit, or the userOp has a paymaster.\n */\n function _payPrefund(uint256 missingAccountFunds) internal virtual {\n if (missingAccountFunds != 0) {\n (bool success,) = payable(msg.sender).call{value : missingAccountFunds, gas : type(uint256).max}(\"\");\n (success);\n //ignore failure (its EntryPoint's job to verify, not account.)\n }\n }\n}\n"
+ },
+ "contracts/core/BasePaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"./Helpers.sol\";\n\n/**\n * Helper class for creating a paymaster.\n * provides helper methods for staking.\n * validates that the postOp is called only by the entryPoint\n */\nabstract contract BasePaymaster is IPaymaster, Ownable {\n\n IEntryPoint immutable public entryPoint;\n\n constructor(IEntryPoint _entryPoint) {\n entryPoint = _entryPoint;\n }\n\n /// @inheritdoc IPaymaster\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external override returns (bytes memory context, uint256 validationData) {\n _requireFromEntryPoint();\n return _validatePaymasterUserOp(userOp, userOpHash, maxCost);\n }\n\n function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal virtual returns (bytes memory context, uint256 validationData);\n\n /// @inheritdoc IPaymaster\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external override {\n _requireFromEntryPoint();\n _postOp(mode, context, actualGasCost);\n }\n\n /**\n * post-operation handler.\n * (verified to be called only through the entryPoint)\n * @dev if subclass returns a non-empty context from validatePaymasterUserOp, it must also implement this method.\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) internal virtual {\n\n (mode,context,actualGasCost); // unused params\n // subclass must override this method if validatePaymasterUserOp returns a context\n revert(\"must override\");\n }\n\n /**\n * add a deposit for this paymaster, used for paying for transaction fees\n */\n function deposit() public payable {\n entryPoint.depositTo{value : msg.value}(address(this));\n }\n\n /**\n * withdraw value from the deposit\n * @param withdrawAddress target to send to\n * @param amount to withdraw\n */\n function withdrawTo(address payable withdrawAddress, uint256 amount) public onlyOwner {\n entryPoint.withdrawTo(withdrawAddress, amount);\n }\n /**\n * add stake for this paymaster.\n * This method can also carry eth value to add to the current stake.\n * @param unstakeDelaySec - the unstake delay for this paymaster. Can only be increased.\n */\n function addStake(uint32 unstakeDelaySec) external payable onlyOwner {\n entryPoint.addStake{value : msg.value}(unstakeDelaySec);\n }\n\n /**\n * return current paymaster's deposit on the entryPoint.\n */\n function getDeposit() public view returns (uint256) {\n return entryPoint.balanceOf(address(this));\n }\n\n /**\n * unlock the stake, in order to withdraw it.\n * The paymaster can't serve requests once unlocked, until it calls addStake again\n */\n function unlockStake() external onlyOwner {\n entryPoint.unlockStake();\n }\n\n /**\n * withdraw the entire paymaster's stake.\n * stake must be unlocked first (and then wait for the unstakeDelay to be over)\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external onlyOwner {\n entryPoint.withdrawStake(withdrawAddress);\n }\n\n /// validate the call is made from a valid entrypoint\n function _requireFromEntryPoint() internal virtual {\n require(msg.sender == address(entryPoint), \"Sender not EntryPoint\");\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/samples/bls/BLSAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../SimpleAccount.sol\";\nimport \"./IBLSAccount.sol\";\n\n/**\n * Minimal BLS-based account that uses an aggregated signature.\n * The account must maintain its own BLS public key, and expose its trusted signature aggregator.\n * Note that unlike the \"standard\" SimpleAccount, this account can't be called directly\n * (normal SimpleAccount uses its \"signer\" address as both the ecrecover signer, and as a legitimate\n * Ethereum sender address. Obviously, a BLS public key is not a valid Ethereum sender address.)\n */\ncontract BLSAccount is SimpleAccount, IBLSAccount {\n address public immutable aggregator;\n uint256[4] private publicKey;\n\n // The constructor is used only for the \"implementation\" and only sets immutable values.\n // Mutable value slots for proxy accounts are set by the 'initialize' function.\n constructor(IEntryPoint anEntryPoint, address anAggregator) SimpleAccount(anEntryPoint) {\n aggregator = anAggregator;\n }\n\n /**\n * The initializer for the BLSAccount instance.\n * @param aPublicKey public key from a BLS keypair that will have a full ownership and control of this account.\n */\n function initialize(uint256[4] memory aPublicKey) public virtual initializer {\n super._initialize(address(0));\n _setBlsPublicKey(aPublicKey);\n }\n\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\n internal override view returns (uint256 validationData) {\n\n (userOp, userOpHash);\n if (userOp.initCode.length != 0) {\n // BLSSignatureAggregator.getUserOpPublicKey() assumes that during account creation, the public key is\n // the suffix of the initCode.\n // The account MUST validate it\n bytes32 pubKeyHash = keccak256(abi.encode(getBlsPublicKey()));\n require(keccak256(userOp.initCode[userOp.initCode.length - 128 :]) == pubKeyHash, \"wrong pubkey\");\n }\n return _packValidationData(ValidationData(aggregator, 0,0));\n }\n\n /**\n * Allows the owner to set or change the BLS key.\n * @param newPublicKey public key from a BLS keypair that will have a full ownership and control of this account.\n */\n function setBlsPublicKey(uint256[4] memory newPublicKey) public onlyOwner {\n _setBlsPublicKey(newPublicKey);\n }\n\n function _setBlsPublicKey(uint256[4] memory newPublicKey) internal {\n emit PublicKeyChanged(publicKey, newPublicKey);\n publicKey = newPublicKey;\n }\n\n /// @inheritdoc IBLSAccount\n function getBlsPublicKey() public override view returns (uint256[4] memory) {\n return publicKey;\n }\n}\n"
+ },
+ "contracts/samples/bls/BLSAccountFactory.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"../../interfaces/IEntryPoint.sol\";\nimport \"./BLSAccount.sol\";\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * Based on SimpleAccountFactory.\n * Cannot be a subclass since both constructor and createAccount depend on the\n * constructor and initializer of the actual account contract.\n */\ncontract BLSAccountFactory {\n BLSAccount public immutable accountImplementation;\n\n constructor(IEntryPoint entryPoint, address aggregator){\n accountImplementation = new BLSAccount(entryPoint, aggregator);\n }\n\n /**\n * create an account, and return its address.\n * returns the address even if the account is already deployed.\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\n * Also note that our BLSSignatureAggregator requires that the public key is the last parameter\n */\n function createAccount(uint256 salt, uint256[4] calldata aPublicKey) public returns (BLSAccount) {\n\n // the BLSSignatureAggregator depends on the public-key being the last 4 uint256 of msg.data.\n uint slot;\n assembly {slot := aPublicKey}\n require(slot == msg.data.length - 128, \"wrong pubkey offset\");\n\n address addr = getAddress(salt, aPublicKey);\n uint codeSize = addr.code.length;\n if (codeSize > 0) {\n return BLSAccount(payable(addr));\n }\n return BLSAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(BLSAccount.initialize, aPublicKey)\n )));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(uint256 salt, uint256[4] memory aPublicKey) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(BLSAccount.initialize, (aPublicKey))\n )\n )));\n }\n}\n"
+ },
+ "contracts/samples/bls/BLSHelper.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n// code taken from : https://github.com/witnet/elliptic-curve-solidity/blob/master/contracts/EllipticCurve.sol\n// missing core functions from \"thehubbleproject/bls\": jacAdd (and sum)\nlibrary BLSHelper {\n\n struct XY {\n uint x;\n uint y;\n }\n /**\n * sum all the points in the array\n * NOTE: the \"ecAdd\" (below) has a special case where x1==y2.\n * @param points an array of bytes32[2], representing an (x,y) of a point\n * @param _pp the modulus of the curve\n * @return ret the sum of all points\n */\n function sum(XY[] memory points, uint256 _pp) internal pure returns (XY memory ret){\n uint x = points[0].x;\n uint y = points[0].y;\n uint z = 1;\n\n for (uint i = 1; i < points.length; i++) {\n (x, y, z) = jacAdd(x, y, z, points[i].x, points[i].y, 1, _pp);\n }\n (x, y) = toAffine(x, y, z, _pp);\n ret.x = x;\n ret.y = y;\n }\n\n /// @dev Adds two points (x1, y1, z1) and (x2, y2, z2).\n /// @param _x1 coordinate x of P1\n /// @param _y1 coordinate y of P1\n /// @param _z1 coordinate z of P1\n /// @param _x2 coordinate x of square\n /// @param _y2 coordinate y of square\n /// @param _z2 coordinate z of square\n /// @param _pp the modulus\n /// @return (qx, qy, qz) P1+square in Jacobian\n function jacAdd(\n uint256 _x1,\n uint256 _y1,\n uint256 _z1,\n uint256 _x2,\n uint256 _y2,\n uint256 _z2,\n uint256 _pp)\n internal pure returns (uint256, uint256, uint256)\n {\n if (_x1 == 0 && _y1 == 0)\n return (_x2, _y2, _z2);\n if (_x2 == 0 && _y2 == 0)\n return (_x1, _y1, _z1);\n\n // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5\n uint[4] memory zs;\n // z1^2, z1^3, z2^2, z2^3\n zs[0] = mulmod(_z1, _z1, _pp);\n zs[1] = mulmod(_z1, zs[0], _pp);\n zs[2] = mulmod(_z2, _z2, _pp);\n zs[3] = mulmod(_z2, zs[2], _pp);\n\n // u1, s1, u2, s2\n zs = [\n mulmod(_x1, zs[2], _pp),\n mulmod(_y1, zs[3], _pp),\n mulmod(_x2, zs[0], _pp),\n mulmod(_y2, zs[1], _pp)\n ];\n\n // In case of zs[0] == zs[2] && zs[1] == zs[3], double function should be used\n require(zs[0] != zs[2] || zs[1] != zs[3], \"Use jacDouble function instead\");\n\n uint[4] memory hr;\n //h\n hr[0] = addmod(zs[2], _pp - zs[0], _pp);\n //r\n hr[1] = addmod(zs[3], _pp - zs[1], _pp);\n //h^2\n hr[2] = mulmod(hr[0], hr[0], _pp);\n // h^3\n hr[3] = mulmod(hr[2], hr[0], _pp);\n // qx = -h^3 -2u1h^2+r^2\n uint256 qx = addmod(mulmod(hr[1], hr[1], _pp), _pp - hr[3], _pp);\n qx = addmod(qx, _pp - mulmod(2, mulmod(zs[0], hr[2], _pp), _pp), _pp);\n // qy = -s1*z1*h^3+r(u1*h^2 -x^3)\n uint256 qy = mulmod(hr[1], addmod(mulmod(zs[0], hr[2], _pp), _pp - qx, _pp), _pp);\n qy = addmod(qy, _pp - mulmod(zs[1], hr[3], _pp), _pp);\n // qz = h*z1*z2\n uint256 qz = mulmod(hr[0], mulmod(_z1, _z2, _pp), _pp);\n return (qx, qy, qz);\n }\n\n\n /// @dev Converts a point (x, y, z) expressed in Jacobian coordinates to affine coordinates (x', y', 1).\n /// @param _x coordinate x\n /// @param _y coordinate y\n /// @param _z coordinate z\n /// @param _pp the modulus\n /// @return (x', y') affine coordinates\n function toAffine(\n uint256 _x,\n uint256 _y,\n uint256 _z,\n uint256 _pp)\n internal pure returns (uint256, uint256)\n {\n uint256 zInv = invMod(_z, _pp);\n uint256 zInv2 = mulmod(zInv, zInv, _pp);\n uint256 x2 = mulmod(_x, zInv2, _pp);\n uint256 y2 = mulmod(_y, mulmod(zInv, zInv2, _pp), _pp);\n\n return (x2, y2);\n }\n\n\n /// @dev Modular euclidean inverse of a number (mod p).\n /// @param _x The number\n /// @param _pp The modulus\n /// @return q such that x*q = 1 (mod _pp)\n function invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) {\n require(_x != 0 && _x != _pp && _pp != 0, \"Invalid number\");\n uint256 q = 0;\n uint256 newT = 1;\n uint256 r = _pp;\n uint256 t;\n while (_x != 0) {\n t = r / _x;\n (q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp));\n (r, _x) = (_x, r - t * _x);\n }\n\n return q;\n }\n\n /// @dev Doubles a point (x, y, z).\n /// @param _x coordinate x of P1\n /// @param _y coordinate y of P1\n /// @param _z coordinate z of P1\n /// @param _aa the a scalar in the curve equation\n /// @param _pp the modulus\n /// @return (qx, qy, qz) 2P in Jacobian\n function jacDouble(\n uint256 _x,\n uint256 _y,\n uint256 _z,\n uint256 _aa,\n uint256 _pp)\n internal pure returns (uint256, uint256, uint256)\n {\n if (_z == 0)\n return (_x, _y, _z);\n\n // We follow the equations described in https://pdfs.semanticscholar.org/5c64/29952e08025a9649c2b0ba32518e9a7fb5c2.pdf Section 5\n // Note: there is a bug in the paper regarding the m parameter, M=3*(x1^2)+a*(z1^4)\n // x, y, z at this point represent the squares of _x, _y, _z\n uint256 x = mulmod(_x, _x, _pp); //x1^2\n uint256 y = mulmod(_y, _y, _pp); //y1^2\n uint256 z = mulmod(_z, _z, _pp); //z1^2\n\n // s\n uint s = mulmod(4, mulmod(_x, y, _pp), _pp);\n // m\n uint m = addmod(mulmod(3, x, _pp), mulmod(_aa, mulmod(z, z, _pp), _pp), _pp);\n\n // x, y, z at this point will be reassigned and rather represent qx, qy, qz from the paper\n // This allows to reduce the gas cost and stack footprint of the algorithm\n // qx\n x = addmod(mulmod(m, m, _pp), _pp - addmod(s, s, _pp), _pp);\n // qy = -8*y1^4 + M(S-T)\n y = addmod(mulmod(m, addmod(s, _pp - x, _pp), _pp), _pp - mulmod(8, mulmod(y, y, _pp), _pp), _pp);\n // qz = 2*y1*z1\n z = mulmod(2, mulmod(_y, _z, _pp), _pp);\n\n return (x, y, z);\n }\n\n /// @dev Add two points (x1, y1) and (x2, y2) in affine coordinates.\n /// @param _x1 coordinate x of P1\n /// @param _y1 coordinate y of P1\n /// @param _x2 coordinate x of P2\n /// @param _y2 coordinate y of P2\n /// @param _aa constant of the curve\n /// @param _pp the modulus\n /// @return (qx, qy) = P1+P2 in affine coordinates\n function ecAdd(\n uint256 _x1,\n uint256 _y1,\n uint256 _x2,\n uint256 _y2,\n uint256 _aa,\n uint256 _pp)\n internal pure returns (uint256, uint256)\n {\n uint x = 0;\n uint y = 0;\n uint z = 0;\n\n // Double if x1==x2 else add\n if (_x1 == _x2) {\n // y1 = -y2 mod p\n if (addmod(_y1, _y2, _pp) == 0) {\n return (0, 0);\n } else {\n // P1 = P2\n (x, y, z) = jacDouble(\n _x1,\n _y1,\n 1,\n _aa,\n _pp);\n }\n } else {\n (x, y, z) = jacAdd(\n _x1,\n _y1,\n 1,\n _x2,\n _y2,\n 1,\n _pp);\n }\n // Get back to affine\n return toAffine(\n x,\n y,\n z,\n _pp);\n }\n\n}\n"
+ },
+ "contracts/samples/bls/BLSSignatureAggregator.sol": {
+ "content": "//SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4 <0.9.0;\npragma abicoder v2;\n\nimport \"../../interfaces/IAggregator.sol\";\nimport \"../../interfaces/IEntryPoint.sol\";\nimport {BLSOpen} from \"./lib/BLSOpen.sol\";\nimport \"./IBLSAccount.sol\";\nimport \"./BLSHelper.sol\";\n\n/**\n * A BLS-based signature aggregator, to validate aggregated signature of multiple UserOps if BLSAccount\n */\ncontract BLSSignatureAggregator is IAggregator {\n using UserOperationLib for UserOperation;\n\n bytes32 public constant BLS_DOMAIN = keccak256(\"eip4337.bls.domain\");\n\n //copied from BLS.sol\n uint256 public constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583;\n\n /**\n * @return publicKey - the public key from a BLS keypair the Aggregator will use to verify this UserOp;\n * normally public key will be queried from the deployed BLSAccount itself;\n * the public key will be read from the 'initCode' if the account is not deployed yet;\n */\n function getUserOpPublicKey(UserOperation memory userOp) public view returns (uint256[4] memory publicKey) {\n bytes memory initCode = userOp.initCode;\n if (initCode.length > 0) {\n publicKey = getTrailingPublicKey(initCode);\n } else {\n return IBLSAccount(userOp.sender).getBlsPublicKey{gas : 50000}();\n }\n }\n\n /**\n * return the trailing 4 words of input data\n */\n function getTrailingPublicKey(bytes memory data) public pure returns (uint256[4] memory publicKey) {\n uint len = data.length;\n require(len > 32 * 4, \"data too short for sig\");\n\n /* solhint-disable-next-line no-inline-assembly */\n assembly {\n // actual buffer starts at data+32, so last 128 bytes start at data+32+len-128 = data+len-96\n let ofs := sub(add(data, len), 96)\n mstore(publicKey, mload(ofs))\n mstore(add(publicKey, 32), mload(add(ofs, 32)))\n mstore(add(publicKey, 64), mload(add(ofs, 64)))\n mstore(add(publicKey, 96), mload(add(ofs, 96)))\n }\n }\n\n /// @inheritdoc IAggregator\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature)\n external view override {\n require(signature.length == 64, \"BLS: invalid signature\");\n (uint256[2] memory blsSignature) = abi.decode(signature, (uint256[2]));\n\n uint userOpsLen = userOps.length;\n uint256[4][] memory blsPublicKeys = new uint256[4][](userOpsLen);\n uint256[2][] memory messages = new uint256[2][](userOpsLen);\n for (uint256 i = 0; i < userOpsLen; i++) {\n\n UserOperation memory userOp = userOps[i];\n blsPublicKeys[i] = getUserOpPublicKey(userOp);\n\n messages[i] = _userOpToMessage(userOp, _getPublicKeyHash(blsPublicKeys[i]));\n }\n require(BLSOpen.verifyMultiple(blsSignature, blsPublicKeys, messages), \"BLS: validateSignatures failed\");\n }\n\n /**\n * get a hash of userOp\n * NOTE: this hash is not the same as UserOperation.hash()\n * (slightly less efficient, since it uses memory userOp)\n */\n function internalUserOpHash(UserOperation memory userOp) internal pure returns (bytes32) {\n return keccak256(abi.encode(\n userOp.sender,\n userOp.nonce,\n keccak256(userOp.initCode),\n keccak256(userOp.callData),\n userOp.callGasLimit,\n userOp.verificationGasLimit,\n userOp.preVerificationGas,\n userOp.maxFeePerGas,\n userOp.maxPriorityFeePerGas,\n keccak256(userOp.paymasterAndData)\n ));\n }\n\n /**\n * return the BLS \"message\" for the given UserOp.\n * the account checks the signature over this value using its public key\n */\n function userOpToMessage(UserOperation memory userOp) public view returns (uint256[2] memory) {\n bytes32 publicKeyHash = _getPublicKeyHash(getUserOpPublicKey(userOp));\n return _userOpToMessage(userOp, publicKeyHash);\n }\n\n function _userOpToMessage(UserOperation memory userOp, bytes32 publicKeyHash) internal view returns (uint256[2] memory) {\n bytes32 userOpHash = _getUserOpHash(userOp, publicKeyHash);\n return BLSOpen.hashToPoint(BLS_DOMAIN, abi.encodePacked(userOpHash));\n }\n\n // helper for test\n function getUserOpHash(UserOperation memory userOp) public view returns (bytes32) {\n bytes32 publicKeyHash = _getPublicKeyHash(getUserOpPublicKey(userOp));\n return _getUserOpHash(userOp, publicKeyHash);\n }\n\n function _getUserOpHash(UserOperation memory userOp, bytes32 publicKeyHash) internal view returns (bytes32) {\n return keccak256(abi.encode(internalUserOpHash(userOp), publicKeyHash, address(this), block.chainid));\n }\n\n function _getPublicKeyHash(uint256[4] memory publicKey) internal pure returns(bytes32) {\n return keccak256(abi.encode(publicKey));\n }\n /**\n * validate signature of a single userOp\n * This method is called after EntryPoint.simulateValidation() returns an aggregator.\n * First it validates the signature over the userOp. then it return data to be used when creating the handleOps:\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp) {\n uint256[2] memory signature = abi.decode(userOp.signature, (uint256[2]));\n uint256[4] memory pubkey = getUserOpPublicKey(userOp);\n uint256[2] memory message = _userOpToMessage(userOp, _getPublicKeyHash(pubkey));\n\n require(BLSOpen.verifySingle(signature, pubkey, message), \"BLS: wrong sig\");\n return \"\";\n }\n\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external pure returns (bytes memory aggregatedSignature) {\n BLSHelper.XY[] memory points = new BLSHelper.XY[](userOps.length);\n for (uint i = 0; i < points.length; i++) {\n (uint256 x, uint256 y) = abi.decode(userOps[i].signature, (uint256, uint256));\n points[i] = BLSHelper.XY(x, y);\n }\n BLSHelper.XY memory sum = BLSHelper.sum(points, N);\n return abi.encode(sum.x, sum.y);\n }\n\n /**\n * allow staking for this aggregator\n * there is no limit on stake or delay, but it is not a problem, since it is a permissionless\n * signature aggregator, which doesn't support unstaking.\n */\n function addStake(IEntryPoint entryPoint, uint32 delay) external payable {\n entryPoint.addStake{value : msg.value}(delay);\n }\n}\n"
+ },
+ "contracts/samples/bls/IBLSAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity >=0.7.6;\n\nimport \"../../interfaces/IAccount.sol\";\n\n/**\n * a BLS account should expose its own public key.\n */\ninterface IBLSAccount is IAccount {\n event PublicKeyChanged(uint256[4] oldPublicKey, uint256[4] newPublicKey);\n\n /**\n * @return public key from a BLS keypair that is used to verify the BLS signature, both separately and aggregated.\n */\n function getBlsPublicKey() external view returns (uint256[4] memory);\n}\n"
+ },
+ "contracts/samples/bls/lib/BLSOpen.sol": {
+ "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.6.12;\n\nimport { BLS } from \"./hubble-contracts/contracts/libs/BLS.sol\";\n\nlibrary BLSOpen {\n function verifySingle(\n uint256[2] memory signature,\n uint256[4] memory pubkey,\n uint256[2] memory message\n ) external view returns (bool) {\n uint256[4][] memory pubkeys = new uint256[4][](1);\n uint256[2][] memory messages = new uint256[2][](1);\n pubkeys[0] = pubkey;\n messages[0] = message;\n\n (bool verified, bool callSuccess) = BLS.verifyMultiple(\n signature,\n pubkeys,\n messages\n );\n return callSuccess && verified;\n\n // // NB: (result, success) opposite of `call` convention (success, result).\n // (bool verified, bool callSuccess) = BLS.verifySingle(\n // signature,\n // pubkey,\n // message\n // );\n // return callSuccess && verified;\n }\n\n function verifyMultiple(\n uint256[2] memory signature,\n uint256[4][] memory pubkeys,\n uint256[2][] memory messages\n ) external view returns (bool) {\n (bool verified, bool callSuccess) = BLS.verifyMultiple(\n signature,\n pubkeys,\n messages\n );\n return callSuccess && verified;\n }\n\n function hashToPoint(\n bytes32 domain,\n bytes memory message\n ) external view returns (uint256[2] memory) {\n return BLS.hashToPoint(\n domain,\n message\n );\n }\n\n function isZeroBLSKey(uint256[4] memory blsKey) public pure returns (bool) {\n bool isZero = true;\n for (uint256 i=0; isZero && i<4; i++) {\n isZero = (blsKey[i] == 0);\n }\n return isZero;\n }\n\n}\n"
+ },
+ "contracts/samples/bls/lib/hubble-contracts/contracts/libs/BLS.sol": {
+ "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.6.12;\n\nimport { ModexpInverse, ModexpSqrt } from \"./ModExp.sol\";\nimport {\n BNPairingPrecompileCostEstimator\n} from \"./BNPairingPrecompileCostEstimator.sol\";\n\n/**\n @title Boneh–Lynn–Shacham (BLS) signature scheme on Barreto-Naehrig 254 bit curve (BN-254)\n @notice We use BLS signature aggregation to reduce the size of signature data to store on chain.\n @dev We use G1 points for signatures and messages, and G2 points for public keys\n */\nlibrary BLS {\n // Field order\n // prettier-ignore\n uint256 private constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583;\n\n // Negated genarator of G2\n // prettier-ignore\n uint256 private constant N_G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;\n // prettier-ignore\n uint256 private constant N_G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;\n // prettier-ignore\n uint256 private constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052;\n // prettier-ignore\n uint256 private constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653;\n\n // sqrt(-3)\n // prettier-ignore\n uint256 private constant Z0 = 0x0000000000000000b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd;\n // (sqrt(-3) - 1) / 2\n // prettier-ignore\n uint256 private constant Z1 = 0x000000000000000059e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe;\n\n // prettier-ignore\n uint256 private constant T24 = 0x1000000000000000000000000000000000000000000000000;\n // prettier-ignore\n uint256 private constant MASK24 = 0xffffffffffffffffffffffffffffffffffffffffffffffff;\n\n // estimator address\n// address private constant COST_ESTIMATOR_ADDRESS = new 0x22E4a5251C1F02de8369Dd6f192033F6CB7531A4;\n\n function verifySingle(\n uint256[2] memory signature,\n uint256[4] memory pubkey,\n uint256[2] memory message\n ) internal view returns (bool, bool) {\n uint256[12] memory input =\n [\n signature[0],\n signature[1],\n N_G2_X1,\n N_G2_X0,\n N_G2_Y1,\n N_G2_Y0,\n message[0],\n message[1],\n pubkey[1],\n pubkey[0],\n pubkey[3],\n pubkey[2]\n ];\n uint256[1] memory out;\n uint256 precompileGasCost = gasleft();\n// BNPairingPrecompileCostEstimator(COST_ESTIMATOR_ADDRESS).getGasCost(\n// 2\n// );\n bool callSuccess;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n callSuccess := staticcall(\n precompileGasCost,\n 8,\n input,\n 384,\n out,\n 0x20\n )\n }\n if (!callSuccess) {\n return (false, false);\n }\n return (out[0] != 0, true);\n }\n\n function verifyMultiple(\n uint256[2] memory signature,\n uint256[4][] memory pubkeys,\n uint256[2][] memory messages\n ) internal view returns (bool checkResult, bool callSuccess) {\n uint256 size = pubkeys.length;\n require(size > 0, \"BLS: number of public key is zero\");\n require(\n size == messages.length,\n \"BLS: number of public keys and messages must be equal\"\n );\n uint256 inputSize = (size + 1) * 6;\n uint256[] memory input = new uint256[](inputSize);\n input[0] = signature[0];\n input[1] = signature[1];\n input[2] = N_G2_X1;\n input[3] = N_G2_X0;\n input[4] = N_G2_Y1;\n input[5] = N_G2_Y0;\n for (uint256 i = 0; i < size; i++) {\n input[i * 6 + 6] = messages[i][0];\n input[i * 6 + 7] = messages[i][1];\n input[i * 6 + 8] = pubkeys[i][1];\n input[i * 6 + 9] = pubkeys[i][0];\n input[i * 6 + 10] = pubkeys[i][3];\n input[i * 6 + 11] = pubkeys[i][2];\n }\n uint256[1] memory out;\n\n // prettier-ignore\n uint256 precompileGasCost = gasleft();\n// uint256 precompileGasCost = BNPairingPrecompileCostEstimator(COST_ESTIMATOR_ADDRESS).getGasCost(size + 1);\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n callSuccess := staticcall(\n precompileGasCost,\n 8,\n add(input, 0x20),\n mul(inputSize, 0x20),\n out,\n 0x20\n )\n }\n if (!callSuccess) {\n return (false, false);\n }\n return (out[0] != 0, true);\n }\n\n /**\n @notice Fouque-Tibouchi Hash to Curve\n */\n function hashToPoint(bytes32 domain, bytes memory message)\n internal\n view\n returns (uint256[2] memory)\n {\n uint256[2] memory u = hashToField(domain, message);\n uint256[2] memory p0 = mapToPoint(u[0]);\n uint256[2] memory p1 = mapToPoint(u[1]);\n uint256[4] memory bnAddInput;\n bnAddInput[0] = p0[0];\n bnAddInput[1] = p0[1];\n bnAddInput[2] = p1[0];\n bnAddInput[3] = p1[1];\n bool success;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n success := staticcall(sub(gas(), 2000), 6, bnAddInput, 128, p0, 64)\n switch success\n case 0 {\n invalid()\n }\n }\n require(success, \"BLS: bn add call failed\");\n return p0;\n }\n\n function mapToPoint(uint256 _x)\n internal\n pure\n returns (uint256[2] memory p)\n {\n require(_x < N, \"mapToPointFT: invalid field element\");\n uint256 x = _x;\n\n (, bool decision) = sqrt(x);\n\n uint256 a0 = mulmod(x, x, N);\n a0 = addmod(a0, 4, N);\n uint256 a1 = mulmod(x, Z0, N);\n uint256 a2 = mulmod(a1, a0, N);\n a2 = inverse(a2);\n a1 = mulmod(a1, a1, N);\n a1 = mulmod(a1, a2, N);\n\n // x1\n a1 = mulmod(x, a1, N);\n x = addmod(Z1, N - a1, N);\n // check curve\n a1 = mulmod(x, x, N);\n a1 = mulmod(a1, x, N);\n a1 = addmod(a1, 3, N);\n bool found;\n (a1, found) = sqrt(a1);\n if (found) {\n if (!decision) {\n a1 = N - a1;\n }\n return [x, a1];\n }\n\n // x2\n x = N - addmod(x, 1, N);\n // check curve\n a1 = mulmod(x, x, N);\n a1 = mulmod(a1, x, N);\n a1 = addmod(a1, 3, N);\n (a1, found) = sqrt(a1);\n if (found) {\n if (!decision) {\n a1 = N - a1;\n }\n return [x, a1];\n }\n\n // x3\n x = mulmod(a0, a0, N);\n x = mulmod(x, x, N);\n x = mulmod(x, a2, N);\n x = mulmod(x, a2, N);\n x = addmod(x, 1, N);\n // must be on curve\n a1 = mulmod(x, x, N);\n a1 = mulmod(a1, x, N);\n a1 = addmod(a1, 3, N);\n (a1, found) = sqrt(a1);\n require(found, \"BLS: bad ft mapping implementation\");\n if (!decision) {\n a1 = N - a1;\n }\n return [x, a1];\n }\n\n function isValidSignature(uint256[2] memory signature)\n internal\n pure\n returns (bool)\n {\n if ((signature[0] >= N) || (signature[1] >= N)) {\n return false;\n } else {\n return isOnCurveG1(signature);\n }\n }\n\n function isOnCurveG1(uint256[2] memory point)\n internal\n pure\n returns (bool _isOnCurve)\n {\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let t0 := mload(point)\n let t1 := mload(add(point, 32))\n let t2 := mulmod(t0, t0, N)\n t2 := mulmod(t2, t0, N)\n t2 := addmod(t2, 3, N)\n t1 := mulmod(t1, t1, N)\n _isOnCurve := eq(t1, t2)\n }\n }\n\n function isOnCurveG2(uint256[4] memory point)\n internal\n pure\n returns (bool _isOnCurve)\n {\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n // x0, x1\n let t0 := mload(point)\n let t1 := mload(add(point, 32))\n // x0 ^ 2\n let t2 := mulmod(t0, t0, N)\n // x1 ^ 2\n let t3 := mulmod(t1, t1, N)\n // 3 * x0 ^ 2\n let t4 := add(add(t2, t2), t2)\n // 3 * x1 ^ 2\n let t5 := addmod(add(t3, t3), t3, N)\n // x0 * (x0 ^ 2 - 3 * x1 ^ 2)\n t2 := mulmod(add(t2, sub(N, t5)), t0, N)\n // x1 * (3 * x0 ^ 2 - x1 ^ 2)\n t3 := mulmod(add(t4, sub(N, t3)), t1, N)\n\n // x ^ 3 + b\n t0 := addmod(\n t2,\n 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5,\n N\n )\n t1 := addmod(\n t3,\n 0x009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2,\n N\n )\n\n // y0, y1\n t2 := mload(add(point, 64))\n t3 := mload(add(point, 96))\n // y ^ 2\n t4 := mulmod(addmod(t2, t3, N), addmod(t2, sub(N, t3), N), N)\n t3 := mulmod(shl(1, t2), t3, N)\n\n // y ^ 2 == x ^ 3 + b\n _isOnCurve := and(eq(t0, t4), eq(t1, t3))\n }\n }\n\n function sqrt(uint256 xx) internal pure returns (uint256 x, bool hasRoot) {\n x = ModexpSqrt.run(xx);\n hasRoot = mulmod(x, x, N) == xx;\n }\n\n function inverse(uint256 a) internal pure returns (uint256) {\n return ModexpInverse.run(a);\n }\n\n function hashToField(bytes32 domain, bytes memory messages)\n internal\n pure\n returns (uint256[2] memory)\n {\n bytes memory _msg = expandMsgTo96(domain, messages);\n uint256 u0;\n uint256 u1;\n uint256 a0;\n uint256 a1;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let p := add(_msg, 24)\n u1 := and(mload(p), MASK24)\n p := add(_msg, 48)\n u0 := and(mload(p), MASK24)\n a0 := addmod(mulmod(u1, T24, N), u0, N)\n p := add(_msg, 72)\n u1 := and(mload(p), MASK24)\n p := add(_msg, 96)\n u0 := and(mload(p), MASK24)\n a1 := addmod(mulmod(u1, T24, N), u0, N)\n }\n return [a0, a1];\n }\n\n function expandMsgTo96(bytes32 domain, bytes memory message)\n internal\n pure\n returns (bytes memory)\n {\n // zero<64>|msg|lib_str<2>|I2OSP(0, 1)<1>|dst|dst_len<1>\n uint256 t0 = message.length;\n bytes memory msg0 = new bytes(32 + t0 + 64 + 4);\n bytes memory out = new bytes(96);\n // b0\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let p := add(msg0, 96)\n for {\n let z := 0\n } lt(z, t0) {\n z := add(z, 32)\n } {\n mstore(add(p, z), mload(add(message, add(z, 32))))\n }\n p := add(p, t0)\n\n mstore8(p, 0)\n p := add(p, 1)\n mstore8(p, 96)\n p := add(p, 1)\n mstore8(p, 0)\n p := add(p, 1)\n\n mstore(p, domain)\n p := add(p, 32)\n mstore8(p, 32)\n }\n bytes32 b0 = sha256(msg0);\n bytes32 bi;\n t0 = 32 + 34;\n\n // resize intermediate message\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n mstore(msg0, t0)\n }\n\n // b1\n\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n mstore(add(msg0, 32), b0)\n mstore8(add(msg0, 64), 1)\n mstore(add(msg0, 65), domain)\n mstore8(add(msg0, add(32, 65)), 32)\n }\n\n bi = sha256(msg0);\n\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n mstore(add(out, 32), bi)\n }\n\n // b2\n\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let t := xor(b0, bi)\n mstore(add(msg0, 32), t)\n mstore8(add(msg0, 64), 2)\n mstore(add(msg0, 65), domain)\n mstore8(add(msg0, add(32, 65)), 32)\n }\n\n bi = sha256(msg0);\n\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n mstore(add(out, 64), bi)\n }\n\n // b3\n\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let t := xor(b0, bi)\n mstore(add(msg0, 32), t)\n mstore8(add(msg0, 64), 3)\n mstore(add(msg0, 65), domain)\n mstore8(add(msg0, add(32, 65)), 32)\n }\n\n bi = sha256(msg0);\n\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n mstore(add(out, 96), bi)\n }\n\n return out;\n }\n}\n"
+ },
+ "contracts/samples/bls/lib/hubble-contracts/contracts/libs/BNPairingPrecompileCostEstimator.sol": {
+ "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.12;\n\ncontract BNPairingPrecompileCostEstimator {\n uint256 public baseCost;\n uint256 public perPairCost;\n\n // G1 Generator\n uint256 private constant G1_X = 1;\n uint256 private constant G1_Y = 2;\n\n // G2 genarator\n // prettier-ignore\n uint256 private constant G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;\n // prettier-ignore\n uint256 private constant G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;\n // prettier-ignore\n uint256 private constant G2_Y0 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;\n // prettier-ignore\n uint256 private constant G2_Y1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;\n\n // G2 negated genarator y coordinates\n // prettier-ignore\n uint256 private constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653;\n // prettier-ignore\n uint256 private constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052;\n\n function run() external {\n _run();\n }\n\n function getGasCost(uint256 pairCount) external view returns (uint256) {\n return pairCount * perPairCost + baseCost;\n }\n\n function _run() internal {\n uint256 gasCost1Pair = _gasCost1Pair();\n uint256 gasCost2Pair = _gasCost2Pair();\n perPairCost = gasCost2Pair - gasCost1Pair;\n baseCost = gasCost1Pair - perPairCost;\n }\n\n function _gasCost1Pair() internal view returns (uint256) {\n uint256[6] memory input = [G1_X, G1_Y, G2_X1, G2_X0, G2_Y1, G2_Y0];\n uint256[1] memory out;\n bool callSuccess;\n uint256 suppliedGas = gasleft() - 2000;\n require(\n gasleft() > 2000,\n \"BNPairingPrecompileCostEstimator: not enough gas, single pair\"\n );\n uint256 gasT0 = gasleft();\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n callSuccess := staticcall(suppliedGas, 8, input, 192, out, 0x20)\n }\n uint256 gasCost = gasT0 - gasleft();\n require(\n callSuccess,\n \"BNPairingPrecompileCostEstimator: single pair call is failed\"\n );\n require(\n out[0] == 0,\n \"BNPairingPrecompileCostEstimator: single pair call result must be 0\"\n );\n return gasCost;\n }\n\n function _gasCost2Pair() internal view returns (uint256) {\n uint256[12] memory input =\n [\n G1_X,\n G1_Y,\n G2_X1,\n G2_X0,\n G2_Y1,\n G2_Y0,\n G1_X,\n G1_Y,\n G2_X1,\n G2_X0,\n N_G2_Y1,\n N_G2_Y0\n ];\n uint256[1] memory out;\n bool callSuccess;\n uint256 suppliedGas = gasleft() - 2000;\n require(\n gasleft() > 2000,\n \"BNPairingPrecompileCostEstimator: not enough gas, couple pair\"\n );\n uint256 gasT0 = gasleft();\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n callSuccess := staticcall(suppliedGas, 8, input, 384, out, 0x20)\n }\n uint256 gasCost = gasT0 - gasleft();\n require(\n callSuccess,\n \"BNPairingPrecompileCostEstimator: couple pair call is failed\"\n );\n require(\n out[0] == 1,\n \"BNPairingPrecompileCostEstimator: couple pair call result must be 1\"\n );\n return gasCost;\n }\n}\n"
+ },
+ "contracts/samples/bls/lib/hubble-contracts/contracts/libs/ModExp.sol": {
+ "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.6.12;\n\n/**\n @title Compute Inverse by Modular Exponentiation\n @notice Compute $input^(N - 2) mod N$ using Addition Chain method.\n Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47\n and N - 2 = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45\n @dev the function body is generated with the modified addchain script\n see https://github.com/kobigurk/addchain/commit/2c37a2ace567a9bdc680b4e929c94aaaa3ec700f\n */\nlibrary ModexpInverse {\n function run(uint256 t2) internal pure returns (uint256 t0) {\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let\n n\n := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47\n t0 := mulmod(t2, t2, n)\n let t5 := mulmod(t0, t2, n)\n let t1 := mulmod(t5, t0, n)\n let t3 := mulmod(t5, t5, n)\n let t8 := mulmod(t1, t0, n)\n let t4 := mulmod(t3, t5, n)\n let t6 := mulmod(t3, t1, n)\n t0 := mulmod(t3, t3, n)\n let t7 := mulmod(t8, t3, n)\n t3 := mulmod(t4, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t7, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t7, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t7, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n }\n }\n}\n\n/**\n @title Compute Squre Root by Modular Exponentiation\n @notice Compute $input^{(N + 1) / 4} mod N$ using Addition Chain method.\n Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47\n and (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52\n */\nlibrary ModexpSqrt {\n function run(uint256 t6) internal pure returns (uint256 t0) {\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n let\n n\n := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47\n\n t0 := mulmod(t6, t6, n)\n let t4 := mulmod(t0, t6, n)\n let t2 := mulmod(t4, t0, n)\n let t3 := mulmod(t4, t4, n)\n let t8 := mulmod(t2, t0, n)\n let t1 := mulmod(t3, t4, n)\n let t5 := mulmod(t3, t2, n)\n t0 := mulmod(t3, t3, n)\n let t7 := mulmod(t8, t3, n)\n t3 := mulmod(t1, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t7, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t7, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t8, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t7, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t6, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t5, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t4, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t3, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t2, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t0, n)\n t0 := mulmod(t0, t1, n)\n t0 := mulmod(t0, t0, n)\n }\n }\n}\n"
+ },
+ "contracts/samples/callback/TokenCallbackHandler.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-empty-blocks */\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport \"@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol\";\n\n/**\n * Token callback handler.\n * Handles supported tokens' callbacks, allowing account receiving these tokens.\n */\ncontract TokenCallbackHandler is IERC777Recipient, IERC721Receiver, IERC1155Receiver {\n function tokensReceived(\n address,\n address,\n address,\n uint256,\n bytes calldata,\n bytes calldata\n ) external pure override {\n }\n\n function onERC721Received(\n address,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (bytes4) {\n return IERC721Receiver.onERC721Received.selector;\n }\n\n function onERC1155Received(\n address,\n address,\n uint256,\n uint256,\n bytes calldata\n ) external pure override returns (bytes4) {\n return IERC1155Receiver.onERC1155Received.selector;\n }\n\n function onERC1155BatchReceived(\n address,\n address,\n uint256[] calldata,\n uint256[] calldata,\n bytes calldata\n ) external pure override returns (bytes4) {\n return IERC1155Receiver.onERC1155BatchReceived.selector;\n }\n\n function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {\n return\n interfaceId == type(IERC721Receiver).interfaceId ||\n interfaceId == type(IERC1155Receiver).interfaceId ||\n interfaceId == type(IERC165).interfaceId;\n }\n}\n"
+ },
+ "contracts/samples/DepositPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../core/BasePaymaster.sol\";\nimport \"./IOracle.sol\";\n\n/**\n * A token-based paymaster that accepts token deposits\n * The deposit is only a safeguard: the user pays with his token balance.\n * only if the user didn't approve() the paymaster, or if the token balance is not enough, the deposit will be used.\n * thus the required deposit is to cover just one method call.\n * The deposit is locked for the current block: the user must issue unlockTokenDeposit() to be allowed to withdraw\n * (but can't use the deposit for this or further operations)\n *\n * paymasterAndData holds the paymaster address followed by the token address to use.\n * @notice This paymaster will be rejected by the standard rules of EIP4337, as it uses an external oracle.\n * (the standard rules ban accessing data of an external contract)\n * It can only be used if it is \"whitelisted\" by the bundler.\n * (technically, it can be used by an \"oracle\" which returns a static value, without accessing any storage)\n */\ncontract DepositPaymaster is BasePaymaster {\n\n using UserOperationLib for UserOperation;\n using SafeERC20 for IERC20;\n\n //calculated cost of the postOp\n uint256 constant public COST_OF_POST = 35000;\n\n IOracle private constant NULL_ORACLE = IOracle(address(0));\n mapping(IERC20 => IOracle) public oracles;\n mapping(IERC20 => mapping(address => uint256)) public balances;\n mapping(address => uint256) public unlockBlock;\n\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) {\n //owner account is unblocked, to allow withdraw of paid tokens;\n unlockTokenDeposit();\n }\n\n /**\n * owner of the paymaster should add supported tokens\n */\n function addToken(IERC20 token, IOracle tokenPriceOracle) external onlyOwner {\n require(oracles[token] == NULL_ORACLE, \"Token already set\");\n oracles[token] = tokenPriceOracle;\n }\n\n /**\n * deposit tokens that a specific account can use to pay for gas.\n * The sender must first approve this paymaster to withdraw these tokens (they are only withdrawn in this method).\n * Note depositing the tokens is equivalent to transferring them to the \"account\" - only the account can later\n * use them - either as gas, or using withdrawTo()\n *\n * @param token the token to deposit.\n * @param account the account to deposit for.\n * @param amount the amount of token to deposit.\n */\n function addDepositFor(IERC20 token, address account, uint256 amount) external {\n //(sender must have approval for the paymaster)\n token.safeTransferFrom(msg.sender, address(this), amount);\n require(oracles[token] != NULL_ORACLE, \"unsupported token\");\n balances[token][account] += amount;\n if (msg.sender == account) {\n lockTokenDeposit();\n }\n }\n\n /**\n * @return amount - the amount of given token deposited to the Paymaster.\n * @return _unlockBlock - the block height at which the deposit can be withdrawn.\n */\n function depositInfo(IERC20 token, address account) public view returns (uint256 amount, uint256 _unlockBlock) {\n amount = balances[token][account];\n _unlockBlock = unlockBlock[account];\n }\n\n /**\n * unlock deposit, so that it can be withdrawn.\n * can't be called in the same block as withdrawTo()\n */\n function unlockTokenDeposit() public {\n unlockBlock[msg.sender] = block.number;\n }\n\n /**\n * lock the tokens deposited for this account so they can be used to pay for gas.\n * after calling unlockTokenDeposit(), the account can't use this paymaster until the deposit is locked.\n */\n function lockTokenDeposit() public {\n unlockBlock[msg.sender] = 0;\n }\n\n /**\n * withdraw tokens.\n * can only be called after unlock() is called in a previous block.\n * @param token the token deposit to withdraw\n * @param target address to send to\n * @param amount amount to withdraw\n */\n function withdrawTokensTo(IERC20 token, address target, uint256 amount) public {\n require(unlockBlock[msg.sender] != 0 && block.number > unlockBlock[msg.sender], \"DepositPaymaster: must unlockTokenDeposit\");\n balances[token][msg.sender] -= amount;\n token.safeTransfer(target, amount);\n }\n\n /**\n * translate the given eth value to token amount\n * @param token the token to use\n * @param ethBought the required eth value we want to \"buy\"\n * @return requiredTokens the amount of tokens required to get this amount of eth\n */\n function getTokenValueOfEth(IERC20 token, uint256 ethBought) internal view virtual returns (uint256 requiredTokens) {\n IOracle oracle = oracles[token];\n require(oracle != NULL_ORACLE, \"DepositPaymaster: unsupported token\");\n return oracle.getTokenValueOfEth(ethBought);\n }\n\n /**\n * Validate the request:\n * The sender should have enough deposit to pay the max possible cost.\n * Note that the sender's balance is not checked. If it fails to pay from its balance,\n * this deposit will be used to compensate the paymaster for the transaction.\n */\n function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal view override returns (bytes memory context, uint256 validationData) {\n\n (userOpHash);\n // verificationGasLimit is dual-purposed, as gas limit for postOp. make sure it is high enough\n require(userOp.verificationGasLimit > COST_OF_POST, \"DepositPaymaster: gas too low for postOp\");\n\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n require(paymasterAndData.length == 20+20, \"DepositPaymaster: paymasterAndData must specify token\");\n IERC20 token = IERC20(address(bytes20(paymasterAndData[20:])));\n address account = userOp.getSender();\n uint256 maxTokenCost = getTokenValueOfEth(token, maxCost);\n uint256 gasPriceUserOp = userOp.gasPrice();\n require(unlockBlock[account] == 0, \"DepositPaymaster: deposit not locked\");\n require(balances[token][account] >= maxTokenCost, \"DepositPaymaster: deposit too low\");\n return (abi.encode(account, token, gasPriceUserOp, maxTokenCost, maxCost),0);\n }\n\n /**\n * perform the post-operation to charge the sender for the gas.\n * in normal mode, use transferFrom to withdraw enough tokens from the sender's balance.\n * in case the transferFrom fails, the _postOp reverts and the entryPoint will call it again,\n * this time in *postOpReverted* mode.\n * In this mode, we use the deposit to pay (which we validated to be large enough)\n */\n function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) internal override {\n\n (address account, IERC20 token, uint256 gasPricePostOp, uint256 maxTokenCost, uint256 maxCost) = abi.decode(context, (address, IERC20, uint256, uint256, uint256));\n //use same conversion rate as used for validation.\n uint256 actualTokenCost = (actualGasCost + COST_OF_POST * gasPricePostOp) * maxTokenCost / maxCost;\n if (mode != PostOpMode.postOpReverted) {\n // attempt to pay with tokens:\n token.safeTransferFrom(account, address(this), actualTokenCost);\n } else {\n //in case above transferFrom failed, pay with deposit:\n balances[token][account] -= actualTokenCost;\n }\n balances[token][owner()] += actualTokenCost;\n }\n}\n"
+ },
+ "contracts/samples/gnosis/EIP4337Fallback.sol": {
+ "content": "//SPDX-License-Identifier: GPL\npragma solidity ^0.8.7;\n\n/* solhint-disable no-inline-assembly */\n\nimport \"@gnosis.pm/safe-contracts/contracts/handler/DefaultCallbackHandler.sol\";\nimport \"@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol\";\nimport \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"../../interfaces/IAccount.sol\";\nimport \"./EIP4337Manager.sol\";\n\nusing ECDSA for bytes32;\n\n/**\n * The GnosisSafe enables adding custom functions implementation to the Safe by setting a 'fallbackHandler'.\n * This 'fallbackHandler' adds an implementation of 'validateUserOp' to the GnosisSafe.\n * Note that the implementation of the 'validateUserOp' method is located in the EIP4337Manager.\n * Upon receiving the 'validateUserOp', a Safe with EIP4337Fallback enabled makes a 'delegatecall' to EIP4337Manager.\n */\ncontract EIP4337Fallback is DefaultCallbackHandler, IAccount, IERC1271 {\n bytes4 internal constant ERC1271_MAGIC_VALUE = 0x1626ba7e;\n\n address immutable public eip4337manager;\n constructor(address _eip4337manager) {\n eip4337manager = _eip4337manager;\n }\n\n /**\n * delegate the contract call to the EIP4337Manager\n */\n function delegateToManager() internal returns (bytes memory) {\n // delegate entire msg.data (including the appended \"msg.sender\") to the EIP4337Manager\n // will work only for GnosisSafe contracts\n GnosisSafe safe = GnosisSafe(payable(msg.sender));\n (bool success, bytes memory ret) = safe.execTransactionFromModuleReturnData(eip4337manager, 0, msg.data, Enum.Operation.DelegateCall);\n if (!success) {\n assembly {\n revert(add(ret, 32), mload(ret))\n }\n }\n return ret;\n }\n\n /**\n * called from the Safe. delegate actual work to EIP4337Manager\n */\n function validateUserOp(UserOperation calldata, bytes32, uint256) override external returns (uint256 deadline){\n bytes memory ret = delegateToManager();\n return abi.decode(ret, (uint256));\n }\n\n /**\n * Helper for wallet to get the next nonce.\n */\n function getNonce() public returns (uint256 nonce) {\n bytes memory ret = delegateToManager();\n (nonce) = abi.decode(ret, (uint256));\n }\n\n /**\n * called from the Safe. delegate actual work to EIP4337Manager\n */\n function executeAndRevert(\n address,\n uint256,\n bytes memory,\n Enum.Operation\n ) external {\n delegateToManager();\n }\n\n function isValidSignature(\n bytes32 _hash,\n bytes memory _signature\n ) external override view returns (bytes4) {\n bytes32 hash = _hash.toEthSignedMessageHash();\n address recovered = hash.recover(_signature);\n\n GnosisSafe safe = GnosisSafe(payable(address(msg.sender)));\n\n // Validate signatures\n if (safe.isOwner(recovered)) {\n return ERC1271_MAGIC_VALUE;\n } else {\n return 0xffffffff;\n }\n }\n}\n"
+ },
+ "contracts/samples/gnosis/EIP4337Manager.sol": {
+ "content": "//SPDX-License-Identifier: GPL\npragma solidity ^0.8.7;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol\";\nimport \"@gnosis.pm/safe-contracts/contracts/base/Executor.sol\";\nimport \"@gnosis.pm/safe-contracts/contracts/examples/libraries/GnosisSafeStorage.sol\";\nimport \"./EIP4337Fallback.sol\";\nimport \"../../interfaces/IAccount.sol\";\nimport \"../../interfaces/IEntryPoint.sol\";\nimport \"../../utils/Exec.sol\";\n\n using ECDSA for bytes32;\n\n/**\n * Main EIP4337 module.\n * Called (through the fallback module) using \"delegate\" from the GnosisSafe as an \"IAccount\",\n * so must implement validateUserOp\n * holds an immutable reference to the EntryPoint\n * Inherits GnosisSafe so that it can reference the memory storage\n */\ncontract EIP4337Manager is IAccount, GnosisSafeStorage, Executor {\n\n address public immutable eip4337Fallback;\n address public immutable entryPoint;\n\n // return value in case of signature failure, with no time-range.\n // equivalent to _packValidationData(true,0,0);\n uint256 constant internal SIG_VALIDATION_FAILED = 1;\n\n address internal constant SENTINEL_MODULES = address(0x1);\n\n constructor(address anEntryPoint) {\n entryPoint = anEntryPoint;\n eip4337Fallback = address(new EIP4337Fallback(address(this)));\n }\n\n /**\n * delegate-called (using execFromModule) through the fallback, so \"real\" msg.sender is attached as last 20 bytes\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external override returns (uint256 validationData) {\n address msgSender = address(bytes20(msg.data[msg.data.length - 20 :]));\n require(msgSender == entryPoint, \"account: not from entrypoint\");\n\n GnosisSafe pThis = GnosisSafe(payable(address(this)));\n bytes32 hash = userOpHash.toEthSignedMessageHash();\n address recovered = hash.recover(userOp.signature);\n require(threshold == 1, \"account: only threshold 1\");\n if (!pThis.isOwner(recovered)) {\n validationData = SIG_VALIDATION_FAILED;\n }\n\n // mimic normal Safe nonce behaviour: prevent parallel nonces\n require(userOp.nonce < type(uint64).max, \"account: nonsequential nonce\");\n\n if (missingAccountFunds > 0) {\n //Note: MAY pay more than the minimum, to deposit for future transactions\n (bool success,) = payable(msgSender).call{value : missingAccountFunds}(\"\");\n (success);\n //ignore failure (its EntryPoint's job to verify, not account.)\n }\n }\n\n /**\n * Execute a call but also revert if the execution fails.\n * The default behavior of the Safe is to not revert if the call fails,\n * which is challenging for integrating with ERC4337 because then the\n * EntryPoint wouldn't know to emit the UserOperationRevertReason event,\n * which the frontend/client uses to capture the reason for the failure.\n */\n function executeAndRevert(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external {\n address msgSender = address(bytes20(msg.data[msg.data.length - 20 :]));\n require(msgSender == entryPoint, \"account: not from entrypoint\");\n require(msg.sender == eip4337Fallback, \"account: not from EIP4337Fallback\");\n\n bool success = execute(\n to,\n value,\n data,\n operation,\n type(uint256).max\n );\n\n bytes memory returnData = Exec.getReturnData(type(uint256).max);\n // Revert with the actual reason string\n // Adopted from: https://github.com/Uniswap/v3-periphery/blob/464a8a49611272f7349c970e0fadb7ec1d3c1086/contracts/base/Multicall.sol#L16-L23\n if (!success) {\n if (returnData.length < 68) revert();\n assembly {\n returnData := add(returnData, 0x04)\n }\n revert(abi.decode(returnData, (string)));\n }\n }\n\n /**\n * Helper for wallet to get the next nonce.\n */\n function getNonce() public view returns (uint256) {\n return IEntryPoint(entryPoint).getNonce(address(this), 0);\n }\n\n /**\n * set up a safe as EIP-4337 enabled.\n * called from the GnosisSafeAccountFactory during construction time\n * - enable 3 modules (this module, fallback and the entrypoint)\n * - this method is called with delegateCall, so the module (usually itself) is passed as parameter, and \"this\" is the safe itself\n */\n function setup4337Modules(\n EIP4337Manager manager //the manager (this contract)\n ) external {\n GnosisSafe safe = GnosisSafe(payable(address(this)));\n require(!safe.isModuleEnabled(manager.entryPoint()), \"setup4337Modules: entrypoint already enabled\");\n require(!safe.isModuleEnabled(manager.eip4337Fallback()), \"setup4337Modules: eip4337Fallback already enabled\");\n safe.enableModule(manager.entryPoint());\n safe.enableModule(manager.eip4337Fallback());\n }\n\n /**\n * replace EIP4337 module, to support a new EntryPoint.\n * must be called using execTransaction and Enum.Operation.DelegateCall\n * @param prevModule returned by getCurrentEIP4337Manager\n * @param oldManager the old EIP4337 manager to remove, returned by getCurrentEIP4337Manager\n * @param newManager the new EIP4337Manager, usually with a new EntryPoint\n */\n function replaceEIP4337Manager(address prevModule, EIP4337Manager oldManager, EIP4337Manager newManager) public {\n GnosisSafe pThis = GnosisSafe(payable(address(this)));\n address oldFallback = oldManager.eip4337Fallback();\n require(pThis.isModuleEnabled(oldFallback), \"replaceEIP4337Manager: oldManager is not active\");\n pThis.disableModule(oldFallback, oldManager.entryPoint());\n pThis.disableModule(prevModule, oldFallback);\n\n address eip4337fallback = newManager.eip4337Fallback();\n\n pThis.enableModule(newManager.entryPoint());\n pThis.enableModule(eip4337fallback);\n pThis.setFallbackHandler(eip4337fallback);\n\n validateEip4337(pThis, newManager);\n }\n\n /**\n * Validate this gnosisSafe is callable through the EntryPoint.\n * the test is might be incomplete: we check that we reach our validateUserOp and fail on signature.\n * we don't test full transaction\n */\n function validateEip4337(GnosisSafe safe, EIP4337Manager manager) public {\n\n // this prevents mistaken replaceEIP4337Manager to disable the module completely.\n // minimal signature that pass \"recover\"\n bytes memory sig = new bytes(65);\n sig[64] = bytes1(uint8(27));\n sig[2] = bytes1(uint8(1));\n sig[35] = bytes1(uint8(1));\n uint256 nonce = uint256(IEntryPoint(manager.entryPoint()).getNonce(address(safe), 0));\n UserOperation memory userOp = UserOperation(address(safe), nonce, \"\", \"\", 0, 1000000, 0, 0, 0, \"\", sig);\n UserOperation[] memory userOps = new UserOperation[](1);\n userOps[0] = userOp;\n IEntryPoint _entryPoint = IEntryPoint(payable(manager.entryPoint()));\n try _entryPoint.handleOps(userOps, payable(msg.sender)) {\n revert(\"validateEip4337: handleOps must fail\");\n } catch (bytes memory error) {\n if (keccak256(error) != keccak256(abi.encodeWithSignature(\"FailedOp(uint256,string)\", 0, \"AA24 signature error\"))) {\n revert(string(error));\n }\n }\n }\n /**\n * enumerate modules, and find the currently active EIP4337 manager (and previous module)\n * @return prev prev module, needed by replaceEIP4337Manager\n * @return manager the current active EIP4337Manager\n */\n function getCurrentEIP4337Manager(GnosisSafe safe) public view returns (address prev, address manager) {\n prev = address(SENTINEL_MODULES);\n (address[] memory modules,) = safe.getModulesPaginated(SENTINEL_MODULES, 100);\n for (uint i = 0; i < modules.length; i++) {\n address module = modules[i];\n try EIP4337Fallback(module).eip4337manager() returns (address _manager) {\n return (prev, _manager);\n }\n // solhint-disable-next-line no-empty-blocks\n catch {}\n prev = module;\n }\n return (address(0), address(0));\n }\n}\n"
+ },
+ "contracts/samples/gnosis/GnosisAccountFactory.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol\";\nimport \"./EIP4337Manager.sol\";\n\n/**\n * A wrapper factory contract to deploy GnosisSafe as an ERC-4337 account contract.\n */\ncontract GnosisSafeAccountFactory {\n\n GnosisSafeProxyFactory public immutable proxyFactory;\n address public immutable safeSingleton;\n EIP4337Manager public immutable eip4337Manager;\n\n constructor(GnosisSafeProxyFactory _proxyFactory, address _safeSingleton, EIP4337Manager _eip4337Manager) {\n proxyFactory = _proxyFactory;\n safeSingleton = _safeSingleton;\n eip4337Manager = _eip4337Manager;\n }\n\n function createAccount(address owner,uint256 salt) public returns (address) {\n address addr = getAddress(owner, salt);\n uint codeSize = addr.code.length;\n if (codeSize > 0) {\n return addr;\n }\n return address(proxyFactory.createProxyWithNonce(\n safeSingleton, getInitializer(owner), salt));\n }\n\n function getInitializer(address owner) internal view returns (bytes memory) {\n address[] memory owners = new address[](1);\n owners[0] = owner;\n uint threshold = 1;\n address eip4337fallback = eip4337Manager.eip4337Fallback();\n\n bytes memory setup4337Modules = abi.encodeCall(\n EIP4337Manager.setup4337Modules, (eip4337Manager));\n\n return abi.encodeCall(GnosisSafe.setup, (\n owners, threshold,\n address (eip4337Manager), setup4337Modules,\n eip4337fallback,\n address(0), 0, payable(0) //no payment receiver\n ));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n * (uses the same \"create2 signature\" used by GnosisSafeProxyFactory.createProxyWithNonce)\n */\n function getAddress(address owner,uint256 salt) public view returns (address) {\n bytes memory initializer = getInitializer(owner);\n //copied from deployProxyWithNonce\n bytes32 salt2 = keccak256(abi.encodePacked(keccak256(initializer), salt));\n bytes memory deploymentData = abi.encodePacked(proxyFactory.proxyCreationCode(), uint256(uint160(safeSingleton)));\n return Create2.computeAddress(bytes32(salt2), keccak256(deploymentData), address (proxyFactory));\n }\n}\n"
+ },
+ "contracts/samples/IOracle.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface IOracle {\n\n /**\n * return amount of tokens that are required to receive that much eth.\n */\n function getTokenValueOfEth(uint256 ethOutput) external view returns (uint256 tokenInput);\n}\n\n"
+ },
+ "contracts/samples/SimpleAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol\";\n\nimport \"../core/BaseAccount.sol\";\nimport \"./callback/TokenCallbackHandler.sol\";\n\n/**\n * minimal account.\n * this is sample minimal account.\n * has execute, eth handling methods\n * has a single signer that can send requests through the entryPoint.\n */\ncontract SimpleAccount is BaseAccount, TokenCallbackHandler, UUPSUpgradeable, Initializable {\n using ECDSA for bytes32;\n\n address public owner;\n\n IEntryPoint private immutable _entryPoint;\n\n event SimpleAccountInitialized(IEntryPoint indexed entryPoint, address indexed owner);\n\n modifier onlyOwner() {\n _onlyOwner();\n _;\n }\n\n /// @inheritdoc BaseAccount\n function entryPoint() public view virtual override returns (IEntryPoint) {\n return _entryPoint;\n }\n\n\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n\n constructor(IEntryPoint anEntryPoint) {\n _entryPoint = anEntryPoint;\n _disableInitializers();\n }\n\n function _onlyOwner() internal view {\n //directly from EOA owner, or through the account itself (which gets redirected through execute())\n require(msg.sender == owner || msg.sender == address(this), \"only owner\");\n }\n\n /**\n * execute a transaction (called directly from owner, or by entryPoint)\n */\n function execute(address dest, uint256 value, bytes calldata func) external {\n _requireFromEntryPointOrOwner();\n _call(dest, value, func);\n }\n\n /**\n * execute a sequence of transactions\n */\n function executeBatch(address[] calldata dest, bytes[] calldata func) external {\n _requireFromEntryPointOrOwner();\n require(dest.length == func.length, \"wrong array lengths\");\n for (uint256 i = 0; i < dest.length; i++) {\n _call(dest[i], 0, func[i]);\n }\n }\n\n /**\n * @dev The _entryPoint member is immutable, to reduce gas consumption. To upgrade EntryPoint,\n * a new implementation of SimpleAccount must be deployed with the new EntryPoint address, then upgrading\n * the implementation by calling `upgradeTo()`\n */\n function initialize(address anOwner) public virtual initializer {\n _initialize(anOwner);\n }\n\n function _initialize(address anOwner) internal virtual {\n owner = anOwner;\n emit SimpleAccountInitialized(_entryPoint, owner);\n }\n\n // Require the function call went through EntryPoint or owner\n function _requireFromEntryPointOrOwner() internal view {\n require(msg.sender == address(entryPoint()) || msg.sender == owner, \"account: not Owner or EntryPoint\");\n }\n\n /// implement template method of BaseAccount\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\n internal override virtual returns (uint256 validationData) {\n bytes32 hash = userOpHash.toEthSignedMessageHash();\n if (owner != hash.recover(userOp.signature))\n return SIG_VALIDATION_FAILED;\n return 0;\n }\n\n function _call(address target, uint256 value, bytes memory data) internal {\n (bool success, bytes memory result) = target.call{value : value}(data);\n if (!success) {\n assembly {\n revert(add(result, 32), mload(result))\n }\n }\n }\n\n /**\n * check current account deposit in the entryPoint\n */\n function getDeposit() public view returns (uint256) {\n return entryPoint().balanceOf(address(this));\n }\n\n /**\n * deposit more funds for this account in the entryPoint\n */\n function addDeposit() public payable {\n entryPoint().depositTo{value : msg.value}(address(this));\n }\n\n /**\n * withdraw value from the account's deposit\n * @param withdrawAddress target to send to\n * @param amount to withdraw\n */\n function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyOwner {\n entryPoint().withdrawTo(withdrawAddress, amount);\n }\n\n function _authorizeUpgrade(address newImplementation) internal view override {\n (newImplementation);\n _onlyOwner();\n }\n}\n\n"
+ },
+ "contracts/samples/SimpleAccountFactory.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"./SimpleAccount.sol\";\n\n/**\n * A sample factory contract for SimpleAccount\n * A UserOperations \"initCode\" holds the address of the factory, and a method call (to createAccount, in this sample factory).\n * The factory's createAccount returns the target account address even if it is already installed.\n * This way, the entryPoint.getSenderAddress() can be called either before or after the account is created.\n */\ncontract SimpleAccountFactory {\n SimpleAccount public immutable accountImplementation;\n\n constructor(IEntryPoint _entryPoint) {\n accountImplementation = new SimpleAccount(_entryPoint);\n }\n\n /**\n * create an account, and return its address.\n * returns the address even if the account is already deployed.\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\n */\n function createAccount(address owner,uint256 salt) public returns (SimpleAccount ret) {\n address addr = getAddress(owner, salt);\n uint codeSize = addr.code.length;\n if (codeSize > 0) {\n return SimpleAccount(payable(addr));\n }\n ret = SimpleAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(SimpleAccount.initialize, (owner))\n )));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(address owner,uint256 salt) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(SimpleAccount.initialize, (owner))\n )\n )));\n }\n}\n"
+ },
+ "contracts/samples/TokenPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable reason-string */\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"../core/BasePaymaster.sol\";\n\n/**\n * A sample paymaster that defines itself as a token to pay for gas.\n * The paymaster IS the token to use, since a paymaster cannot use an external contract.\n * Also, the exchange rate has to be fixed, since it can't reference an external Uniswap or other exchange contract.\n * subclass should override \"getTokenValueOfEth\" to provide actual token exchange rate, settable by the owner.\n * Known Limitation: this paymaster is exploitable when put into a batch with multiple ops (of different accounts):\n * - while a single op can't exploit the paymaster (if postOp fails to withdraw the tokens, the user's op is reverted,\n * and then we know we can withdraw the tokens), multiple ops with different senders (all using this paymaster)\n * in a batch can withdraw funds from 2nd and further ops, forcing the paymaster itself to pay (from its deposit)\n * - Possible workarounds are either use a more complex paymaster scheme (e.g. the DepositPaymaster) or\n * to whitelist the account and the called method ids.\n */\ncontract TokenPaymaster is BasePaymaster, ERC20 {\n\n //calculated cost of the postOp\n uint256 constant public COST_OF_POST = 15000;\n\n address public immutable theFactory;\n\n constructor(address accountFactory, string memory _symbol, IEntryPoint _entryPoint) ERC20(_symbol, _symbol) BasePaymaster(_entryPoint) {\n theFactory = accountFactory;\n //make it non-empty\n _mint(address(this), 1);\n\n //owner is allowed to withdraw tokens from the paymaster's balance\n _approve(address(this), msg.sender, type(uint).max);\n }\n\n\n /**\n * helpers for owner, to mint and withdraw tokens.\n * @param recipient - the address that will receive the minted tokens.\n * @param amount - the amount it will receive.\n */\n function mintTokens(address recipient, uint256 amount) external onlyOwner {\n _mint(recipient, amount);\n }\n\n /**\n * transfer paymaster ownership.\n * owner of this paymaster is allowed to withdraw funds (tokens transferred to this paymaster's balance)\n * when changing owner, the old owner's withdrawal rights are revoked.\n */\n function transferOwnership(address newOwner) public override virtual onlyOwner {\n // remove allowance of current owner\n _approve(address(this), owner(), 0);\n super.transferOwnership(newOwner);\n // new owner is allowed to withdraw tokens from the paymaster's balance\n _approve(address(this), newOwner, type(uint).max);\n }\n\n //Note: this method assumes a fixed ratio of token-to-eth. subclass should override to supply oracle\n // or a setter.\n function getTokenValueOfEth(uint256 valueEth) internal view virtual returns (uint256 valueToken) {\n return valueEth / 100;\n }\n\n /**\n * validate the request:\n * if this is a constructor call, make sure it is a known account.\n * verify the sender has enough tokens.\n * (since the paymaster is also the token, there is no notion of \"approval\")\n */\n function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 /*userOpHash*/, uint256 requiredPreFund)\n internal view override returns (bytes memory context, uint256 validationData) {\n uint256 tokenPrefund = getTokenValueOfEth(requiredPreFund);\n\n // verificationGasLimit is dual-purposed, as gas limit for postOp. make sure it is high enough\n // make sure that verificationGasLimit is high enough to handle postOp\n require(userOp.verificationGasLimit > COST_OF_POST, \"TokenPaymaster: gas too low for postOp\");\n\n if (userOp.initCode.length != 0) {\n _validateConstructor(userOp);\n require(balanceOf(userOp.sender) >= tokenPrefund, \"TokenPaymaster: no balance (pre-create)\");\n } else {\n\n require(balanceOf(userOp.sender) >= tokenPrefund, \"TokenPaymaster: no balance\");\n }\n\n return (abi.encode(userOp.sender), 0);\n }\n\n // when constructing an account, validate constructor code and parameters\n // we trust our factory (and that it doesn't have any other public methods)\n function _validateConstructor(UserOperation calldata userOp) internal virtual view {\n address factory = address(bytes20(userOp.initCode[0 : 20]));\n require(factory == theFactory, \"TokenPaymaster: wrong account factory\");\n }\n\n /**\n * actual charge of user.\n * this method will be called just after the user's TX with mode==OpSucceeded|OpReverted (account pays in both cases)\n * BUT: if the user changed its balance in a way that will cause postOp to revert, then it gets called again, after reverting\n * the user's TX , back to the state it was before the transaction started (before the validatePaymasterUserOp),\n * and the transaction should succeed there.\n */\n function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) internal override {\n //we don't really care about the mode, we just pay the gas with the user's tokens.\n (mode);\n address sender = abi.decode(context, (address));\n uint256 charge = getTokenValueOfEth(actualGasCost + COST_OF_POST);\n //actualGasCost is known to be no larger than the above requiredPreFund, so the transfer should succeed.\n _transfer(sender, address(this), charge);\n }\n}\n"
+ },
+ "contracts/samples/VerifyingPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable reason-string */\n/* solhint-disable no-inline-assembly */\n\nimport \"../core/BasePaymaster.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\n/**\n * A sample paymaster that uses external service to decide whether to pay for the UserOp.\n * The paymaster trusts an external signer to sign the transaction.\n * The calling user must pass the UserOp to that external signer first, which performs\n * whatever off-chain verification before signing the UserOp.\n * Note that this signature is NOT a replacement for the account-specific signature:\n * - the paymaster checks a signature to agree to PAY for GAS.\n * - the account checks a signature to prove identity and account ownership.\n */\ncontract VerifyingPaymaster is BasePaymaster {\n\n using ECDSA for bytes32;\n using UserOperationLib for UserOperation;\n\n address public immutable verifyingSigner;\n\n uint256 private constant VALID_TIMESTAMP_OFFSET = 20;\n\n uint256 private constant SIGNATURE_OFFSET = 84;\n\n constructor(IEntryPoint _entryPoint, address _verifyingSigner) BasePaymaster(_entryPoint) {\n verifyingSigner = _verifyingSigner;\n }\n\n mapping(address => uint256) public senderNonce;\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n // lighter signature scheme. must match UserOp.ts#packUserOp\n bytes calldata pnd = userOp.paymasterAndData;\n // copy directly the userOp from calldata up to (but not including) the paymasterAndData.\n // this encoding depends on the ABI encoding of calldata, but is much lighter to copy\n // than referencing each field separately.\n assembly {\n let ofs := userOp\n let len := sub(sub(pnd.offset, ofs), 32)\n ret := mload(0x40)\n mstore(0x40, add(ret, add(len, 32)))\n mstore(ret, len)\n calldatacopy(add(ret, 32), ofs, len)\n }\n }\n\n /**\n * return the hash we're going to sign off-chain (and validate on-chain)\n * this method is called by the off-chain service, to sign the request.\n * it is called on-chain from the validatePaymasterUserOp, to validate the signature.\n * note that this signature covers all fields of the UserOperation, except the \"paymasterAndData\",\n * which will carry the signature itself.\n */\n function getHash(UserOperation calldata userOp, uint48 validUntil, uint48 validAfter)\n public view returns (bytes32) {\n //can't use userOp.hash(), since it contains also the paymasterAndData itself.\n\n return keccak256(abi.encode(\n pack(userOp),\n block.chainid,\n address(this),\n senderNonce[userOp.getSender()],\n validUntil,\n validAfter\n ));\n }\n\n /**\n * verify our external signer signed this request.\n * the \"paymasterAndData\" is expected to be the paymaster and a signature over the entire request params\n * paymasterAndData[:20] : address(this)\n * paymasterAndData[20:84] : abi.encode(validUntil, validAfter)\n * paymasterAndData[84:] : signature\n */\n function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 /*userOpHash*/, uint256 requiredPreFund)\n internal override returns (bytes memory context, uint256 validationData) {\n (requiredPreFund);\n\n (uint48 validUntil, uint48 validAfter, bytes calldata signature) = parsePaymasterAndData(userOp.paymasterAndData);\n //ECDSA library supports both 64 and 65-byte long signatures.\n // we only \"require\" it here so that the revert reason on invalid signature will be of \"VerifyingPaymaster\", and not \"ECDSA\"\n require(signature.length == 64 || signature.length == 65, \"VerifyingPaymaster: invalid signature length in paymasterAndData\");\n bytes32 hash = ECDSA.toEthSignedMessageHash(getHash(userOp, validUntil, validAfter));\n senderNonce[userOp.getSender()]++;\n\n //don't revert on signature failure: return SIG_VALIDATION_FAILED\n if (verifyingSigner != ECDSA.recover(hash, signature)) {\n return (\"\",_packValidationData(true,validUntil,validAfter));\n }\n\n //no need for other on-chain validation: entire UserOp should have been checked\n // by the external service prior to signing it.\n return (\"\",_packValidationData(false,validUntil,validAfter));\n }\n\n function parsePaymasterAndData(bytes calldata paymasterAndData) public pure returns(uint48 validUntil, uint48 validAfter, bytes calldata signature) {\n (validUntil, validAfter) = abi.decode(paymasterAndData[VALID_TIMESTAMP_OFFSET:SIGNATURE_OFFSET],(uint48, uint48));\n signature = paymasterAndData[SIGNATURE_OFFSET:];\n }\n}\n"
+ },
+ "contracts/test/BrokenBlsAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"../samples/SimpleAccount.sol\";\nimport \"../samples/bls/IBLSAccount.sol\";\n\n/**\n * for testing: a BLS account that fails to return its public-key (completely ignores its publickey)\n * this is a copy of the normal bls account, but it returns a public-key unrelated to the one it is constructed with.\n */\ncontract BrokenBLSAccount is SimpleAccount, IBLSAccount {\n address public immutable aggregator;\n\n // The constructor is used only for the \"implementation\" and only sets immutable values.\n // Mutable values slots for proxy accounts are set by the 'initialize' function.\n constructor(IEntryPoint anEntryPoint, address anAggregator) SimpleAccount(anEntryPoint) {\n aggregator = anAggregator;\n }\n\n function initialize(uint256[4] memory aPublicKey) public virtual initializer {\n (aPublicKey);\n super._initialize(address(0));\n }\n\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\n internal override view returns (uint256 validationData) {\n\n (userOp, userOpHash);\n return _packValidationData(ValidationData(aggregator, 0,0));\n }\n\n function getBlsPublicKey() external override pure returns (uint256[4] memory) {\n uint256[4] memory pubkey;\n return pubkey;\n }\n}\n\n\n/**\n * Based n SimpleAccountFactory\n * can't be a subclass, since both constructor and createAccount depend on the\n * actual wallet contract constructor and initializer\n */\ncontract BrokenBLSAccountFactory {\n BrokenBLSAccount public immutable accountImplementation;\n\n constructor(IEntryPoint entryPoint, address aggregator){\n accountImplementation = new BrokenBLSAccount(entryPoint, aggregator);\n }\n\n /**\n * create an account, and return its address.\n * returns the address even if the account is already deployed.\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\n * Also note that out BLSSignatureAggregator requires that the public-key is the last parameter\n */\n function createAccount(uint salt, uint256[4] memory aPublicKey) public returns (BrokenBLSAccount) {\n\n address addr = getAddress(salt, aPublicKey);\n uint codeSize = addr.code.length;\n if (codeSize > 0) {\n return BrokenBLSAccount(payable(addr));\n }\n return BrokenBLSAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(BrokenBLSAccount.initialize, aPublicKey)\n )));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(uint salt, uint256[4] memory aPublicKey) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(BrokenBLSAccount.initialize, (aPublicKey))\n )\n )));\n }\n}\n"
+ },
+ "contracts/test/MaliciousAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../core/EntryPoint.sol\";\n\ncontract MaliciousAccount is IAccount {\n IEntryPoint private ep;\n constructor(IEntryPoint _ep) payable {\n ep = _ep;\n }\n function validateUserOp(UserOperation calldata userOp, bytes32, uint256 missingAccountFunds)\n external returns (uint256 validationData) {\n ep.depositTo{value : missingAccountFunds}(address(this));\n // Now calculate basefee per EntryPoint.getUserOpGasPrice() and compare it to the basefe we pass off-chain in the signature\n uint256 externalBaseFee = abi.decode(userOp.signature, (uint256));\n uint256 requiredGas = userOp.callGasLimit + userOp.verificationGasLimit + userOp.preVerificationGas;\n uint256 gasPrice = missingAccountFunds / requiredGas;\n uint256 basefee = gasPrice - userOp.maxPriorityFeePerGas;\n require (basefee == externalBaseFee, \"Revert after first validation\");\n return 0;\n }\n}\n"
+ },
+ "contracts/test/TestAggregatedAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../samples/SimpleAccount.sol\";\n\n/**\n * test aggregated-signature account.\n * works only with TestAggregatedSignature, which doesn't really check signature, but nonce sum\n * a true aggregated account should expose data (e.g. its public key) to the aggregator.\n */\ncontract TestAggregatedAccount is SimpleAccount {\n address public immutable aggregator;\n\n // The constructor is used only for the \"implementation\" and only sets immutable values.\n // Mutable value slots for proxy accounts are set by the 'initialize' function.\n constructor(IEntryPoint anEntryPoint, address anAggregator) SimpleAccount(anEntryPoint) {\n aggregator = anAggregator;\n }\n\n /// @inheritdoc SimpleAccount\n function initialize(address) public virtual override initializer {\n super._initialize(address(0));\n }\n\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\n internal override view returns (uint256 validationData) {\n (userOp, userOpHash);\n return _packValidationData(ValidationData(aggregator, 0, 0));\n }\n}\n"
+ },
+ "contracts/test/TestAggregatedAccountFactory.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\nimport \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\n\nimport \"./TestAggregatedAccount.sol\";\n\n/**\n * Based on SimpleAccountFactory.\n * Cannot be a subclass since both constructor and createAccount depend on the\n * constructor and initializer of the actual account contract.\n */\ncontract TestAggregatedAccountFactory {\n TestAggregatedAccount public immutable accountImplementation;\n\n constructor(IEntryPoint anEntryPoint, address anAggregator){\n accountImplementation = new TestAggregatedAccount(anEntryPoint, anAggregator);\n }\n\n /**\n * create an account, and return its address.\n * returns the address even if the account is already deployed.\n * Note that during UserOperation execution, this method is called only if the account is not deployed.\n * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after account creation\n */\n function createAccount(address owner,uint256 salt) public returns (TestAggregatedAccount ret) {\n address addr = getAddress(owner, salt);\n uint codeSize = addr.code.length;\n if (codeSize > 0) {\n return TestAggregatedAccount(payable(addr));\n }\n ret = TestAggregatedAccount(payable(new ERC1967Proxy{salt : bytes32(salt)}(\n address(accountImplementation),\n abi.encodeCall(TestAggregatedAccount.initialize, (owner))\n )));\n }\n\n /**\n * calculate the counterfactual address of this account as it would be returned by createAccount()\n */\n function getAddress(address owner,uint256 salt) public view returns (address) {\n return Create2.computeAddress(bytes32(salt), keccak256(abi.encodePacked(\n type(ERC1967Proxy).creationCode,\n abi.encode(\n address(accountImplementation),\n abi.encodeCall(TestAggregatedAccount.initialize, (owner))\n )\n )));\n }\n}\n"
+ },
+ "contracts/test/TestCounter.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n//sample \"receiver\" contract, for testing \"exec\" from account.\ncontract TestCounter {\n mapping(address => uint256) public counters;\n\n function count() public {\n counters[msg.sender] = counters[msg.sender] + 1;\n }\n\n function countFail() public pure {\n revert(\"count failed\");\n }\n\n function justemit() public {\n emit CalledFrom(msg.sender);\n }\n\n event CalledFrom(address sender);\n\n //helper method to waste gas\n // repeat - waste gas on writing storage in a loop\n // junk - dynamic buffer to stress the function size.\n mapping(uint256 => uint256) public xxx;\n uint256 public offset;\n\n function gasWaster(uint256 repeat, string calldata /*junk*/) external {\n for (uint256 i = 1; i <= repeat; i++) {\n offset++;\n xxx[offset] = i;\n }\n }\n}\n"
+ },
+ "contracts/test/TestExpirePaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../core/BasePaymaster.sol\";\n\n/**\n * test expiry mechanism: paymasterData encodes the \"validUntil\" and validAfter\" times\n */\ncontract TestExpirePaymaster is BasePaymaster {\n // solhint-disable no-empty-blocks\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint)\n {}\n\n function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n (userOp, userOpHash, maxCost);\n (uint48 validAfter, uint48 validUntil) = abi.decode(userOp.paymasterAndData[20 :], (uint48, uint48));\n validationData = _packValidationData(false, validUntil, validAfter);\n context = \"\";\n }\n}\n"
+ },
+ "contracts/test/TestExpiryAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../samples/SimpleAccount.sol\";\n\n/**\n * A test account, for testing expiry.\n * add \"temporary\" owners, each with a time range (since..till) times for each.\n * NOTE: this is not a full \"session key\" implementation: a real session key should probably limit\n * other things, like target contracts and methods to be called.\n * also, the \"since\" value is not really useful, only for testing the entrypoint.\n */\ncontract TestExpiryAccount is SimpleAccount {\n using ECDSA for bytes32;\n\n mapping(address => uint48) public ownerAfter;\n mapping(address => uint48) public ownerUntil;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(IEntryPoint anEntryPoint) SimpleAccount(anEntryPoint) {}\n\n function initialize(address anOwner) public virtual override initializer {\n super._initialize(anOwner);\n addTemporaryOwner(anOwner, 0, type(uint48).max);\n }\n\n // As this is a test contract, no need for proxy, so no need to disable init\n // solhint-disable-next-line no-empty-blocks\n function _disableInitializers() internal override {}\n\n function addTemporaryOwner(address owner, uint48 _after, uint48 _until) public onlyOwner {\n require(_until > _after, \"wrong until/after\");\n ownerAfter[owner] = _after;\n ownerUntil[owner] = _until;\n }\n\n /// implement template method of BaseAccount\n function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)\n internal override view returns (uint256 validationData) {\n bytes32 hash = userOpHash.toEthSignedMessageHash();\n address signer = hash.recover(userOp.signature);\n uint48 _until = ownerUntil[signer];\n uint48 _after = ownerAfter[signer];\n\n //we have \"until\" value for all valid owners. so zero means \"invalid signature\"\n bool sigFailed = _until == 0;\n return _packValidationData(sigFailed, _until, _after);\n }\n}\n"
+ },
+ "contracts/test/TestHelpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../core/Helpers.sol\";\n\ncontract TestHelpers {\n\n function parseValidationData(uint validationData) public pure returns (ValidationData memory) {\n return _parseValidationData(validationData);\n }\n\n function intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) public pure returns (ValidationData memory) {\n return _intersectTimeRange(validationData, paymasterValidationData);\n }\n\n function packValidationDataStruct(ValidationData memory data) public pure returns (uint256) {\n return _packValidationData(data);\n }\n\n function packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) public pure returns (uint256) {\n return _packValidationData(sigFailed, validUntil, validAfter);\n }\n}\n"
+ },
+ "contracts/test/TestOracle.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../samples/IOracle.sol\";\n\ncontract TestOracle is IOracle {\n function getTokenValueOfEth(uint256 ethOutput) external pure override returns (uint256 tokenInput) {\n return ethOutput * 2;\n }\n}\n"
+ },
+ "contracts/test/TestPaymasterAcceptAll.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../core/BasePaymaster.sol\";\n\n/**\n * test paymaster, that pays for everything, without any check.\n */\ncontract TestPaymasterAcceptAll is BasePaymaster {\n\n constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint) {\n // to support \"deterministic address\" factory\n // solhint-disable avoid-tx-origin\n if (tx.origin != msg.sender) {\n _transferOwnership(tx.origin);\n }\n\n }\n\n function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n internal virtual override view\n returns (bytes memory context, uint256 validationData) {\n (userOp, userOpHash, maxCost);\n return (\"\", maxCost == 12345 ? 1 : 0);\n }\n}\n"
+ },
+ "contracts/test/TestRevertAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n/* solhint-disable no-inline-assembly */\n\nimport \"../samples/SimpleAccount.sol\";\ncontract TestRevertAccount is IAccount {\n IEntryPoint private ep;\n constructor(IEntryPoint _ep) payable {\n ep = _ep;\n }\n\n function validateUserOp(UserOperation calldata, bytes32, uint256 missingAccountFunds)\n external override returns (uint256 validationData) {\n ep.depositTo{value : missingAccountFunds}(address(this));\n return 0;\n }\n\n function revertLong(uint256 length) public pure{\n assembly {\n revert(0, length)\n }\n }\n}\n"
+ },
+ "contracts/test/TestSignatureAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable reason-string */\n\nimport \"../interfaces/IAggregator.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../samples/SimpleAccount.sol\";\n\n/**\n * test signature aggregator.\n * the aggregated signature is the SUM of the nonce fields..\n */\ncontract TestSignatureAggregator is IAggregator {\n\n /// @inheritdoc IAggregator\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external pure override {\n uint sum = 0;\n for (uint i = 0; i < userOps.length; i++) {\n uint nonce = userOps[i].nonce;\n sum += nonce;\n }\n require(signature.length == 32, \"TestSignatureValidator: sig must be uint\");\n (uint sig) = abi.decode(signature, (uint));\n require(sig == sum, \"TestSignatureValidator: aggregated signature mismatch (nonce sum)\");\n }\n\n /// @inheritdoc IAggregator\n function validateUserOpSignature(UserOperation calldata)\n external pure returns (bytes memory) {\n return \"\";\n }\n\n /**\n * dummy test aggregator: sum all nonce values of UserOps.\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external pure returns (bytes memory aggregatedSignature) {\n uint sum = 0;\n for (uint i = 0; i < userOps.length; i++) {\n sum += userOps[i].nonce;\n }\n return abi.encode(sum);\n }\n\n /**\n * Calls the 'addStake' method of the EntryPoint. Forwards the entire msg.value to this call.\n * @param entryPoint - the EntryPoint to send the stake to.\n * @param delay - the new lock duration before the deposit can be withdrawn.\n */\n function addStake(IEntryPoint entryPoint, uint32 delay) external payable {\n entryPoint.addStake{value: msg.value}(delay);\n }\n}\n"
+ },
+ "contracts/test/TestToken.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestToken is ERC20 {\n constructor ()\n // solhint-disable-next-line no-empty-blocks\n ERC20(\"TST\", \"TestToken\") {\n }\n\n function mint(address sender, uint256 amount) external {\n _mint(sender, amount);\n }\n}\n"
+ },
+ "contracts/test/TestUtil.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/UserOperation.sol\";\n\ncontract TestUtil {\n using UserOperationLib for UserOperation;\n\n function packUserOp(UserOperation calldata op) external pure returns (bytes memory){\n return op.pack();\n }\n\n}\n"
+ },
+ "contracts/test/TestWarmColdAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IEntryPoint.sol\";\nimport \"../interfaces/IAccount.sol\";\n\n// Using eip-2929 (https://eips.ethereum.org/EIPS/eip-2929) warm/cold storage access gas costs to detect simulation vs execution\n// COLD_ACCOUNT_ACCESS_COST == 2600, COLD_SLOAD_COST == 2100, WARM_STORAGE_READ_COST == 100\ncontract TestWarmColdAccount is IAccount {\n IEntryPoint private ep;\n uint public state = 1;\n constructor(IEntryPoint _ep) payable {\n ep = _ep;\n }\n\n function validateUserOp(UserOperation calldata userOp, bytes32, uint256 missingAccountFunds)\n external override returns (uint256 validationData) {\n ep.depositTo{value : missingAccountFunds}(address(this));\n if (userOp.nonce == 1) {\n // can only succeed if storage is already warm\n this.touchStorage{gas: 1000}();\n } else if (userOp.nonce == 2) {\n address paymaster = address(bytes20(userOp.paymasterAndData[: 20]));\n // can only succeed if storage is already warm\n this.touchPaymaster{gas: 1000}(paymaster);\n }\n return 0;\n }\n\n function touchStorage() public view returns (uint256) {\n return state;\n }\n\n function touchPaymaster(address paymaster) public view returns (uint256) {\n return paymaster.code.length;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata",
+ "devdoc",
+ "userdoc",
+ "storageLayout",
+ "evm.gasEstimates"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ },
+ "metadata": {
+ "useLiteralContent": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/cfbebdf1101dd2bc0f310cb0b7d62cb7.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/cfbebdf1101dd2bc0f310cb0b7d62cb7.json
new file mode 100644
index 000000000..dd27f82ce
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mainnet/solcInputs/cfbebdf1101dd2bc0f310cb0b7d62cb7.json
@@ -0,0 +1,59 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n revert SenderAddressResult(senderCreator.createSender(initCode));\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\n\ninterface IEntryPoint is IStakeManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n /**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n //lighter signature scheme. must match UserOp.ts#packUserOp\n bytes calldata sig = userOp.signature;\n // copy directly the userOp from calldata up to (but not including) the signature.\n // this encoding depends on the ABI encoding of calldata, but is much lighter to copy\n // than referencing each field separately.\n assembly {\n let ofs := userOp\n let len := sub(sub(sig.offset, ofs), 32)\n ret := mload(0x40)\n mstore(0x40, add(ret, add(len, 32)))\n mstore(ret, len)\n calldatacopy(add(ret, 32), ofs, len)\n }\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/.chainId
new file mode 100644
index 000000000..065fd3e79
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/.chainId
@@ -0,0 +1 @@
+137
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/EntryPoint.json
new file mode 100644
index 000000000..037750fba
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 2,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/solcInputs/cfbebdf1101dd2bc0f310cb0b7d62cb7.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/solcInputs/cfbebdf1101dd2bc0f310cb0b7d62cb7.json
new file mode 100644
index 000000000..dd27f82ce
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/matic/solcInputs/cfbebdf1101dd2bc0f310cb0b7d62cb7.json
@@ -0,0 +1,59 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n revert SenderAddressResult(senderCreator.createSender(initCode));\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\n\ninterface IEntryPoint is IStakeManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n /**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n //lighter signature scheme. must match UserOp.ts#packUserOp\n bytes calldata sig = userOp.signature;\n // copy directly the userOp from calldata up to (but not including) the signature.\n // this encoding depends on the ABI encoding of calldata, but is much lighter to copy\n // than referencing each field separately.\n assembly {\n let ofs := userOp\n let len := sub(sub(sig.offset, ofs), 32)\n ret := mload(0x40)\n mstore(0x40, add(ret, add(len, 32)))\n mstore(ret, len)\n calldatacopy(add(ret, 32), ofs, len)\n }\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/.chainId
new file mode 100644
index 000000000..d7e2f72ce
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/.chainId
@@ -0,0 +1 @@
+80001
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/EntryPoint.json
new file mode 100644
index 000000000..916c23908
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 1,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/mumbai/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/.chainId
new file mode 100644
index 000000000..9a037142a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/.chainId
@@ -0,0 +1 @@
+10
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/EntryPoint.json
new file mode 100644
index 000000000..916c23908
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 1,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/optimism/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/.chainId b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/.chainId
new file mode 100644
index 000000000..bd8d1cd44
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/.chainId
@@ -0,0 +1 @@
+11155111
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/EntryPoint.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/EntryPoint.json
new file mode 100644
index 000000000..916c23908
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/EntryPoint.json
@@ -0,0 +1,1318 @@
+{
+ "address": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "paid",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bool",
+ "name": "targetSuccess",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetResult",
+ "type": "bytes"
+ }
+ ],
+ "name": "ExecutionResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "opIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "string",
+ "name": "reason",
+ "type": "string"
+ }
+ ],
+ "name": "FailedOp",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ }
+ ],
+ "name": "SenderAddressResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureValidationFailed",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResult",
+ "type": "error"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bool",
+ "name": "sigFailed",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validAfter",
+ "type": "uint48"
+ },
+ {
+ "internalType": "uint48",
+ "name": "validUntil",
+ "type": "uint48"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterContext",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.ReturnInfo",
+ "name": "returnInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "senderInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "factoryInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "paymasterInfo",
+ "type": "tuple"
+ },
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "components": [
+ {
+ "internalType": "uint256",
+ "name": "stake",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct IStakeManager.StakeInfo",
+ "name": "stakeInfo",
+ "type": "tuple"
+ }
+ ],
+ "internalType": "struct IEntryPoint.AggregatorStakeInfo",
+ "name": "aggregatorInfo",
+ "type": "tuple"
+ }
+ ],
+ "name": "ValidationResultWithAggregation",
+ "type": "error"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "factory",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ }
+ ],
+ "name": "AccountDeployed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [],
+ "name": "BeforeExecution",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalDeposit",
+ "type": "uint256"
+ }
+ ],
+ "name": "Deposited",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "aggregator",
+ "type": "address"
+ }
+ ],
+ "name": "SignatureAggregatorChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "totalStaked",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "unstakeDelaySec",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeLocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "withdrawTime",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeUnlocked",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeWithdrawn",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "success",
+ "type": "bool"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "actualGasUsed",
+ "type": "uint256"
+ }
+ ],
+ "name": "UserOperationEvent",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes",
+ "name": "revertReason",
+ "type": "bytes"
+ }
+ ],
+ "name": "UserOperationRevertReason",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "Withdrawn",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "SIG_VALIDATION_FAILED",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ }
+ ],
+ "name": "_validateSenderAndPaymaster",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ }
+ ],
+ "name": "addStake",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "depositTo",
+ "outputs": [],
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "name": "deposits",
+ "outputs": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
+ }
+ ],
+ "name": "getDepositInfo",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "uint112",
+ "name": "deposit",
+ "type": "uint112"
+ },
+ {
+ "internalType": "bool",
+ "name": "staked",
+ "type": "bool"
+ },
+ {
+ "internalType": "uint112",
+ "name": "stake",
+ "type": "uint112"
+ },
+ {
+ "internalType": "uint32",
+ "name": "unstakeDelaySec",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint48",
+ "name": "withdrawTime",
+ "type": "uint48"
+ }
+ ],
+ "internalType": "struct IStakeManager.DepositInfo",
+ "name": "info",
+ "type": "tuple"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "getNonce",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ }
+ ],
+ "name": "getSenderAddress",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "getUserOpHash",
+ "outputs": [
+ {
+ "internalType": "bytes32",
+ "name": "",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "userOps",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "contract IAggregator",
+ "name": "aggregator",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct IEntryPoint.UserOpsPerAggregator[]",
+ "name": "opsPerAggregator",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleAggregatedOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation[]",
+ "name": "ops",
+ "type": "tuple[]"
+ },
+ {
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ }
+ ],
+ "name": "handleOps",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint192",
+ "name": "key",
+ "type": "uint192"
+ }
+ ],
+ "name": "incrementNonce",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "components": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "address",
+ "name": "paymaster",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.MemoryUserOp",
+ "name": "mUserOp",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "userOpHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "prefund",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "contextOffset",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preOpGas",
+ "type": "uint256"
+ }
+ ],
+ "internalType": "struct EntryPoint.UserOpInfo",
+ "name": "opInfo",
+ "type": "tuple"
+ },
+ {
+ "internalType": "bytes",
+ "name": "context",
+ "type": "bytes"
+ }
+ ],
+ "name": "innerHandleOp",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "actualGasCost",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ },
+ {
+ "internalType": "uint192",
+ "name": "",
+ "type": "uint192"
+ }
+ ],
+ "name": "nonceSequenceNumber",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "op",
+ "type": "tuple"
+ },
+ {
+ "internalType": "address",
+ "name": "target",
+ "type": "address"
+ },
+ {
+ "internalType": "bytes",
+ "name": "targetCallData",
+ "type": "bytes"
+ }
+ ],
+ "name": "simulateHandleOp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "sender",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nonce",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "initCode",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "callData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "uint256",
+ "name": "callGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "verificationGasLimit",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "preVerificationGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "uint256",
+ "name": "maxPriorityFeePerGas",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "paymasterAndData",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "signature",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct UserOperation",
+ "name": "userOp",
+ "type": "tuple"
+ }
+ ],
+ "name": "simulateValidation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "unlockStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdrawStake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address payable",
+ "name": "withdrawAddress",
+ "type": "address"
+ },
+ {
+ "internalType": "uint256",
+ "name": "withdrawAmount",
+ "type": "uint256"
+ }
+ ],
+ "name": "withdrawTo",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "stateMutability": "payable",
+ "type": "receive"
+ }
+ ],
+ "args": [],
+ "numDeployments": 1,
+ "solcInputHash": "a4c52f0671aad8941c53d6ead2063803",
+ "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"struct IStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"struct IEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"BeforeExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"struct IStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct IEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint192\",\"name\":\"key\",\"type\":\"uint192\"}],\"name\":\"incrementNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"struct EntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"name\":\"nonceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct UserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"errors\":{\"FailedOp(uint256,string)\":[{\"params\":{\"opIndex\":\"- index into the array of ops to the failed one (in simulateValidation, this is always zero)\",\"reason\":\"- revert reason The string starts with a unique code \\\"AAmn\\\", where \\\"m\\\" is \\\"1\\\" for factory, \\\"2\\\" for account and \\\"3\\\" for paymaster issues, so a failure can be attributed to the correct entity. Should be caught in off-chain handleOps simulation and not happen on-chain. Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\"}}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"params\":{\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"params\":{\"aggregatorInfo\":\"signature aggregation info (if the account requires signature aggregator) bundler MUST use it to verify the signature, or reject the UserOperation\",\"factoryInfo\":\"stake information about the factory (if any)\",\"paymasterInfo\":\"stake information about the paymaster (if any)\",\"returnInfo\":\"gas and time-range returned values\",\"senderInfo\":\"stake information about the sender\"}}]},\"kind\":\"dev\",\"methods\":{\"addStake(uint32)\":{\"params\":{\"unstakeDelaySec\":\"the new lock duration before the deposit can be withdrawn.\"}},\"getDepositInfo(address)\":{\"returns\":{\"info\":\"- full deposit information of given account\"}},\"getNonce(address,uint192)\":{\"params\":{\"key\":\"the high 192 bit of the nonce\",\"sender\":\"the account address\"},\"returns\":{\"nonce\":\"a full nonce to pass for next UserOp with this sender.\"}},\"getSenderAddress(bytes)\":{\"params\":{\"initCode\":\"the constructor code to be passed into the UserOperation.\"}},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"opsPerAggregator\":\"the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\"}},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"params\":{\"beneficiary\":\"the address to receive the fees\",\"ops\":\"the operations to execute\"}},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"params\":{\"op\":\"the UserOperation to simulate\",\"target\":\"if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult are set to the return from that call.\",\"targetCallData\":\"callData to pass to target address\"}},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"details\":\"this method always revert. Successful result is ValidationResult error. other errors are failures.The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\",\"params\":{\"userOp\":\"the user operation to validate.\"}},\"withdrawStake(address)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\"}},\"withdrawTo(address,uint256)\":{\"params\":{\"withdrawAddress\":\"the address to send withdrawn value.\",\"withdrawAmount\":\"the amount to withdraw.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ExecutionResult(uint256,uint256,uint48,uint48,bool,bytes)\":[{\"notice\":\"return value of simulateHandleOp\"}],\"FailedOp(uint256,string)\":[{\"notice\":\"a custom revert error of handleOps, to identify the offending op. NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\"}],\"SenderAddressResult(address)\":[{\"notice\":\"return value of getSenderAddress\"}],\"SignatureValidationFailed(address)\":[{\"notice\":\"error case when a signature aggregator fails to verify the aggregated signature it had created.\"}],\"ValidationResult((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256))\":[{\"notice\":\"Successful result from simulateValidation.\"}],\"ValidationResultWithAggregation((uint256,uint256,bool,uint48,uint48,bytes),(uint256,uint256),(uint256,uint256),(uint256,uint256),(address,(uint256,uint256)))\":[{\"notice\":\"Successful result from simulateValidation, if the account returns a signature aggregator\"}]},\"events\":{\"AccountDeployed(bytes32,address,address,address)\":{\"notice\":\"account \\\"sender\\\" was deployed.\"},\"BeforeExecution()\":{\"notice\":\"an event emitted by handleOps(), before starting the execution loop. any event emitted before this event, is part of the validation.\"},\"SignatureAggregatorChanged(address)\":{\"notice\":\"signature aggregator used by the following UserOperationEvents within this bundle.\"},\"StakeLocked(address,uint256,uint256)\":{\"notice\":\"Emitted when stake or unstake delay are modified\"},\"StakeUnlocked(address,uint256)\":{\"notice\":\"Emitted once a stake is scheduled for withdrawal\"},\"UserOperationRevertReason(bytes32,address,uint256,bytes)\":{\"notice\":\"An event emitted if the UserOperation \\\"callData\\\" reverted with non-zero length\"}},\"kind\":\"user\",\"methods\":{\"SIG_VALIDATION_FAILED()\":{\"notice\":\"for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value in case of signature failure, instead of revert.\"},\"_validateSenderAndPaymaster(bytes,address,bytes)\":{\"notice\":\"Called only during simulation. This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\"},\"addStake(uint32)\":{\"notice\":\"add to the account's stake - amount and delay any pending unstake is first cancelled.\"},\"balanceOf(address)\":{\"notice\":\"return the deposit (for gas payment) of the account\"},\"depositTo(address)\":{\"notice\":\"add to the deposit of the given account\"},\"deposits(address)\":{\"notice\":\"maps paymaster to their deposits and stakes\"},\"getNonce(address,uint192)\":{\"notice\":\"Return the next nonce for this sender. Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) But UserOp with different keys can come with arbitrary order.\"},\"getSenderAddress(bytes)\":{\"notice\":\"Get counterfactual sender address. Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. this method always revert, and returns the address in SenderAddressResult error\"},\"getUserOpHash((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"generate a request Id - unique identifier for this request. the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\"},\"handleAggregatedOps(((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperation with Aggregators\"},\"handleOps((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes)[],address)\":{\"notice\":\"Execute a batch of UserOperations. no signature aggregator is used. if any account requires an aggregator (that is, it returned an aggregator when performing simulateValidation), then handleAggregatedOps() must be used instead.\"},\"incrementNonce(uint192)\":{\"notice\":\"Manually increment the nonce of the sender. This method is exposed just for completeness.. Account does NOT need to call it, neither during validation, nor elsewhere, as the EntryPoint will update the nonce regardless. Possible use-case is call it with various keys to \\\"initialize\\\" their nonces to one, so that future UserOperations will not pay extra for the first transaction with a given key.\"},\"innerHandleOp(bytes,((address,uint256,uint256,uint256,uint256,address,uint256,uint256),bytes32,uint256,uint256,uint256),bytes)\":{\"notice\":\"inner function to handle a UserOperation. Must be declared \\\"external\\\" to open a call context, but it can only be called by handleOps.\"},\"nonceSequenceNumber(address,uint192)\":{\"notice\":\"The next valid sequence number for a given nonce key.\"},\"simulateHandleOp((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes),address,bytes)\":{\"notice\":\"simulate full execution of a UserOperation (including both validation and target execution) this method will always revert with \\\"ExecutionResult\\\". it performs full validation of the UserOperation, but ignores signature error. an optional target address is called after the userop succeeds, and its value is returned (before the entire call is reverted) Note that in order to collect the the success/failure of the target call, it must be executed with trace enabled to track the emitted events.\"},\"simulateValidation((address,uint256,bytes,bytes,uint256,uint256,uint256,uint256,uint256,bytes,bytes))\":{\"notice\":\"Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\"},\"unlockStake()\":{\"notice\":\"attempt to unlock the stake. the value can be withdrawn (using withdrawStake) after the unstake delay.\"},\"withdrawStake(address)\":{\"notice\":\"withdraw from the (unlocked) stake. must first call unlockStake and wait for the unstakeDelay to pass\"},\"withdrawTo(address,uint256)\":{\"notice\":\"withdraw from the deposit.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/core/EntryPoint.sol\":\"EntryPoint\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"keccak256\":\"0x190dd6f8d592b7e4e930feb7f4313aeb8e1c4ad3154c27ce1cf6a512fc30d8cc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4ce8dfb62d0c4fa260d6eec8f1cd47f5f2a044e11bde5b31d18072fa6e7d9010\",\"dweb:/ipfs/QmTyFztU3tLEcEDnqqiaW4UJetqsU77LXc6pjc9oTXCK5u\"]},\"contracts/core/EntryPoint.sol\":{\"keccak256\":\"0x04f86318b47f052d7308795ffae6ecec0d023d2458b4e17751b89a0e4acfcdc6\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://c9f6e359c8dbe875ad974d3a0fb7b3d62319a6b115c44bac1e4587ae2ad2edaf\",\"dweb:/ipfs/QmTSWTov2rUeYk8cwzrtsd3uVXokCYok4gMiZ1sPs9tycH\"]},\"contracts/core/Helpers.sol\":{\"keccak256\":\"0x591c87519f7155d1909210276b77925ab2722a99b7b5d5649aecc36ebbdb045a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://69643e83f68e6a13d5075c7565bfce326673b0bd98c432033c4603ea84835746\",\"dweb:/ipfs/QmSwSzjYyV7qudi5vvsmzHMG2Z4YJZxX51RRXXVCLaNcEU\"]},\"contracts/core/NonceManager.sol\":{\"keccak256\":\"0xa17a4a6fde70088ab18ffe6df830f3efa31f1cd0e1a7160336c96e3c94984d25\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://b38615df9f80c56282b72888e9ba1eb1a9413fa67a0dbf094deda7af9feb38e7\",\"dweb:/ipfs/QmSzcXetEJRH4UHuUmZiSgX6bFgfqHWfmyuxVnh4NosMk1\"]},\"contracts/core/SenderCreator.sol\":{\"keccak256\":\"0x44b9449fec82d6cdfb01d52fdd5a72f90099c651316123810cf9633f00b018c2\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a9c0487390e72638681d175c45bc92425c802fffdca4bd0ae8457782ee284612\",\"dweb:/ipfs/QmVbzuehCUWJWqEHyMWuc6cRVbxfcMdFsmGL9o4Wz7WY2x\"]},\"contracts/core/StakeManager.sol\":{\"keccak256\":\"0x21aa0956382bd000b1b8c3b1d19ca6ebcd6c9029eebb19c612fb38ee5dd2430a\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://0a625c8795354d9f429367f9c1d14eb8af7db9c7f2c2a2033e2066ced76a573a\",\"dweb:/ipfs/Qmd1j6UarUg54q1G2HCNCLQz8XGVZR1qxX7eQ6cytHpQPN\"]},\"contracts/interfaces/IAccount.sol\":{\"keccak256\":\"0x556a0e5980de18e90b115553ed502408155ba35f58642823010d9288047bc418\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://a0f420134b79596db8737173c7b933ae0a33059e107b6327c43aa40d4744a9e4\",\"dweb:/ipfs/QmRo8s1AhXmEMV7uPYnbpYwU19e9Bk6jmYBJTiPx3Fo85W\"]},\"contracts/interfaces/IAggregator.sol\":{\"keccak256\":\"0x060e9ddb0152250c269ba0640dc5753834ac44cf182a2837d508c0c529cae26a\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://20ed837bc5909c89ff1910246bf245a5dad6840aa939382e1694964eb7dbd37b\",\"dweb:/ipfs/QmTMybRq5yyghPDDs1ZCNAVB9sSJ4WHe6Q9mejuKPTAdNP\"]},\"contracts/interfaces/IEntryPoint.sol\":{\"keccak256\":\"0x3a90bf308819ed125fa4202f880999caff8a8686633b8ddb79a30ca240d5b8f8\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://d2d21cc92c2fdab2b58d21bc25d4cd0e8c284b922528a186b087b818d54bc6cf\",\"dweb:/ipfs/QmT1qrfuBjsv2rmRCDn8mgPXHp94hARJwzbcDuBLDTbFWd\"]},\"contracts/interfaces/INonceManager.sol\":{\"keccak256\":\"0x509871e6c63663cdcc3eba19920fe84e991f38b289b1377ac3c3a6d9f22d7e12\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://00fe21b4349b24c50df60e1a705179293982bd9e7a32b78d4bac9620f89e7fe2\",\"dweb:/ipfs/QmSFFYGfUwQbVa6hASjU7YxTvgi2HkfrPr4X5oPHscHg8b\"]},\"contracts/interfaces/IPaymaster.sol\":{\"keccak256\":\"0x36858ba8685024974f533530420688da3454d29996ebc42e410673a1ed2ec456\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://616cbcf51778b1961b7f20a547bec7efae6d1d565df0f651926241ed8bde9ad8\",\"dweb:/ipfs/QmaVsgffUUmeUJYgStvRr8cNZ1LBbrc3FYNLW4JT1dVLia\"]},\"contracts/interfaces/IStakeManager.sol\":{\"keccak256\":\"0xd227b02888cd4ac68daebcdfd992ec00f9fff66fa3b3bb16f656cd582fa3480f\",\"license\":\"GPL-3.0-only\",\"urls\":[\"bzz-raw://b389da4714a138be63704a576a482505eab2855e263b38a93706395d8d42e7c3\",\"dweb:/ipfs/QmeeAZpdHwUXxqP8pxA7GNtoCGBmmH4FaqLLwScVKGxtxZ\"]},\"contracts/interfaces/UserOperation.sol\":{\"keccak256\":\"0x61374003361059087fdcf17967a7bba052badeaf5c7f0ae689166f8aafd3a45c\",\"license\":\"GPL-3.0\",\"urls\":[\"bzz-raw://6ff83c59432e733bf6304dda27cd4b0f34401917dd535e2669cc842d2d26568c\",\"dweb:/ipfs/QmPJbHU5TAjHqUTZzAcicEeG2nknmwCN43L4EW9LHbknTN\"]},\"contracts/utils/Exec.sol\":{\"keccak256\":\"0x5b232117afbc2939f3ffc92745614867e9e1d475a3e1e5443adae13c200174f1\",\"license\":\"LGPL-3.0-only\",\"urls\":[\"bzz-raw://62e7365379a06ead7b47637945bcaee095d51aab1d3ac00ddec69443e6cbe9fe\",\"dweb:/ipfs/QmctG3aw4U3KMSMeJKoLJ1NJewjMWfppnd1m3kxNTe39Uy\"]}},\"version\":1}",
+ "bytecode": "0x60a080604052346200008957600160025561022c8181016001600160401b038111838210176200007357829162005d18833903906000f080156200006757608052604051615c8990816200008f82396080518181816113df01528181613e9501526141b60152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033",
+ "deployedBytecode": "0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033"
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/solcInputs/a4c52f0671aad8941c53d6ead2063803.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
new file mode 100644
index 000000000..dd58ba5a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/deployments/sepolia/solcInputs/a4c52f0671aad8941c53d6ead2063803.json
@@ -0,0 +1,68 @@
+{
+ "language": "Solidity",
+ "sources": {
+ "@openzeppelin/contracts/security/ReentrancyGuard.sol": {
+ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n"
+ },
+ "contracts/core/EntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n\nimport \"../interfaces/IAccount.sol\";\nimport \"../interfaces/IPaymaster.sol\";\nimport \"../interfaces/IEntryPoint.sol\";\n\nimport \"../utils/Exec.sol\";\nimport \"./StakeManager.sol\";\nimport \"./SenderCreator.sol\";\nimport \"./Helpers.sol\";\nimport \"./NonceManager.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\ncontract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {\n\n using UserOperationLib for UserOperation;\n\n SenderCreator private immutable senderCreator = new SenderCreator();\n\n // internal value used during simulation: need to query aggregator.\n address private constant SIMULATE_FIND_AGGREGATOR = address(1);\n\n // marker for inner call revert on out of gas\n bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead';\n\n uint256 private constant REVERT_REASON_MAX_LEN = 2048;\n\n /**\n * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value\n * in case of signature failure, instead of revert.\n */\n uint256 public constant SIG_VALIDATION_FAILED = 1;\n\n /**\n * compensate the caller's beneficiary address with the collected fees of all UserOperations.\n * @param beneficiary the address to receive the fees\n * @param amount amount to transfer.\n */\n function _compensate(address payable beneficiary, uint256 amount) internal {\n require(beneficiary != address(0), \"AA90 invalid beneficiary\");\n (bool success,) = beneficiary.call{value : amount}(\"\");\n require(success, \"AA91 failed send to beneficiary\");\n }\n\n /**\n * execute a user op\n * @param opIndex index into the opInfo array\n * @param userOp the userOp to execute\n * @param opInfo the opInfo filled by validatePrepayment for this userOp.\n * @return collected the total amount this userOp paid.\n */\n function _executeUserOp(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) {\n uint256 preGas = gasleft();\n bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);\n\n try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) {\n collected = _actualGasCost;\n } catch {\n bytes32 innerRevertCode;\n assembly {\n returndatacopy(0, 0, 32)\n innerRevertCode := mload(0)\n }\n // handleOps was called with gas limit too low. abort entire bundle.\n if (innerRevertCode == INNER_OUT_OF_GAS) {\n //report paymaster, since if it is not deliberately caused by the bundler,\n // it must be a revert caused by paymaster.\n revert FailedOp(opIndex, \"AA95 out of gas\");\n }\n\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas);\n }\n }\n\n /**\n * Execute a batch of UserOperations.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) public nonReentrant {\n\n uint256 opslen = ops.length;\n UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);\n\n unchecked {\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[i];\n (uint256 validationData, uint256 pmValidationData) = _validatePrepayment(i, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, pmValidationData, address(0));\n }\n\n uint256 collected = 0;\n emit BeforeExecution();\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(i, ops[i], opInfos[i]);\n }\n\n _compensate(beneficiary, collected);\n } //unchecked\n }\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) public nonReentrant {\n\n uint256 opasLen = opsPerAggregator.length;\n uint256 totalOps = 0;\n for (uint256 i = 0; i < opasLen; i++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[i];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n //address(1) is special marker of \"signature error\"\n require(address(aggregator) != address(1), \"AA96 invalid aggregator\");\n\n if (address(aggregator) != address(0)) {\n // solhint-disable-next-line no-empty-blocks\n try aggregator.validateSignatures(ops, opa.signature) {}\n catch {\n revert SignatureValidationFailed(address(aggregator));\n }\n }\n\n totalOps += ops.length;\n }\n\n UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);\n\n emit BeforeExecution();\n\n uint256 opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n UserOperation[] calldata ops = opa.userOps;\n IAggregator aggregator = opa.aggregator;\n\n uint256 opslen = ops.length;\n for (uint256 i = 0; i < opslen; i++) {\n UserOpInfo memory opInfo = opInfos[opIndex];\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(opIndex, ops[i], opInfo);\n _validateAccountAndPaymasterValidationData(i, validationData, paymasterValidationData, address(aggregator));\n opIndex++;\n }\n }\n\n uint256 collected = 0;\n opIndex = 0;\n for (uint256 a = 0; a < opasLen; a++) {\n UserOpsPerAggregator calldata opa = opsPerAggregator[a];\n emit SignatureAggregatorChanged(address(opa.aggregator));\n UserOperation[] calldata ops = opa.userOps;\n uint256 opslen = ops.length;\n\n for (uint256 i = 0; i < opslen; i++) {\n collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]);\n opIndex++;\n }\n }\n emit SignatureAggregatorChanged(address(0));\n\n _compensate(beneficiary, collected);\n }\n\n /// @inheritdoc IEntryPoint\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override {\n\n UserOpInfo memory opInfo;\n _simulationOnlyValidations(op);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo);\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n\n numberMarker();\n uint256 paid = _executeUserOp(0, op, opInfo);\n numberMarker();\n bool targetSuccess;\n bytes memory targetResult;\n if (target != address(0)) {\n (targetSuccess, targetResult) = target.call(targetCallData);\n }\n revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult);\n }\n\n\n // A memory copy of UserOp static fields only.\n // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.\n struct MemoryUserOp {\n address sender;\n uint256 nonce;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n address paymaster;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n }\n\n struct UserOpInfo {\n MemoryUserOp mUserOp;\n bytes32 userOpHash;\n uint256 prefund;\n uint256 contextOffset;\n uint256 preOpGas;\n }\n\n /**\n * inner function to handle a UserOperation.\n * Must be declared \"external\" to open a call context, but it can only be called by handleOps.\n */\n function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes calldata context) external returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n require(msg.sender == address(this), \"AA92 internal call only\");\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n\n uint callGasLimit = mUserOp.callGasLimit;\n unchecked {\n // handleOps was called with gas limit too low. abort entire bundle.\n if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) {\n assembly {\n mstore(0, INNER_OUT_OF_GAS)\n revert(0, 32)\n }\n }\n }\n\n IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;\n if (callData.length > 0) {\n bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);\n if (!success) {\n bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);\n if (result.length > 0) {\n emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);\n }\n mode = IPaymaster.PostOpMode.opReverted;\n }\n }\n\n unchecked {\n uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;\n //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp)\n return _handlePostOp(0, mode, opInfo, context, actualGas);\n }\n }\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) {\n return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));\n }\n\n /**\n * copy general fields from userOp into the memory opInfo structure.\n */\n function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {\n mUserOp.sender = userOp.sender;\n mUserOp.nonce = userOp.nonce;\n mUserOp.callGasLimit = userOp.callGasLimit;\n mUserOp.verificationGasLimit = userOp.verificationGasLimit;\n mUserOp.preVerificationGas = userOp.preVerificationGas;\n mUserOp.maxFeePerGas = userOp.maxFeePerGas;\n mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes calldata paymasterAndData = userOp.paymasterAndData;\n if (paymasterAndData.length > 0) {\n require(paymasterAndData.length >= 20, \"AA93 invalid paymasterAndData\");\n mUserOp.paymaster = address(bytes20(paymasterAndData[: 20]));\n } else {\n mUserOp.paymaster = address(0);\n }\n }\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external {\n UserOpInfo memory outOpInfo;\n\n _simulationOnlyValidations(userOp);\n (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo);\n StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);\n StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);\n StakeInfo memory factoryInfo;\n {\n bytes calldata initCode = userOp.initCode;\n address factory = initCode.length >= 20 ? address(bytes20(initCode[0 : 20])) : address(0);\n factoryInfo = _getStakeInfo(factory);\n }\n\n ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData);\n address aggregator = data.aggregator;\n bool sigFailed = aggregator == address(1);\n ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund,\n sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset));\n\n if (aggregator != address(0) && aggregator != address(1)) {\n AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));\n revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);\n }\n revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo);\n\n }\n\n function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {\n unchecked {\n //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.\n // our security model might call postOp eventually twice\n uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1;\n uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas;\n\n requiredPrefund = requiredGas * mUserOp.maxFeePerGas;\n }\n }\n\n // create the sender's contract if needed.\n function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {\n if (initCode.length != 0) {\n address sender = opInfo.mUserOp.sender;\n if (sender.code.length != 0) revert FailedOp(opIndex, \"AA10 sender already constructed\");\n address sender1 = senderCreator.createSender{gas : opInfo.mUserOp.verificationGasLimit}(initCode);\n if (sender1 == address(0)) revert FailedOp(opIndex, \"AA13 initCode failed or OOG\");\n if (sender1 != sender) revert FailedOp(opIndex, \"AA14 initCode must return sender\");\n if (sender1.code.length == 0) revert FailedOp(opIndex, \"AA15 initCode must create sender\");\n address factory = address(bytes20(initCode[0 : 20]));\n emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);\n }\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes calldata initCode) public {\n address sender = senderCreator.createSender(initCode);\n revert SenderAddressResult(sender);\n }\n\n function _simulationOnlyValidations(UserOperation calldata userOp) internal view {\n // solhint-disable-next-line no-empty-blocks\n try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {}\n catch Error(string memory revertReason) {\n if (bytes(revertReason).length != 0) {\n revert FailedOp(0, revertReason);\n }\n }\n }\n\n /**\n * Called only during simulation.\n * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.\n */\n function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view {\n if (initCode.length == 0 && sender.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA20 account not deployed\");\n }\n if (paymasterAndData.length >= 20) {\n address paymaster = address(bytes20(paymasterAndData[0 : 20]));\n if (paymaster.code.length == 0) {\n // it would revert anyway. but give a meaningful message\n revert(\"AA30 paymaster not deployed\");\n }\n }\n // always revert\n revert(\"\");\n }\n\n /**\n * call account.validateUserOp.\n * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.\n * decrement account's deposit if needed\n */\n function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund)\n internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) {\n unchecked {\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n address sender = mUserOp.sender;\n _createSenderIfNeeded(opIndex, opInfo, op.initCode);\n address paymaster = mUserOp.paymaster;\n numberMarker();\n uint256 missingAccountFunds = 0;\n if (paymaster == address(0)) {\n uint256 bal = balanceOf(sender);\n missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;\n }\n try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)\n returns (uint256 _validationData) {\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA23 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA23 reverted (or OOG)\");\n }\n if (paymaster == address(0)) {\n DepositInfo storage senderInfo = deposits[sender];\n uint256 deposit = senderInfo.deposit;\n if (requiredPrefund > deposit) {\n revert FailedOp(opIndex, \"AA21 didn't pay prefund\");\n }\n senderInfo.deposit = uint112(deposit - requiredPrefund);\n }\n gasUsedByValidateAccountPrepayment = preGas - gasleft();\n }\n }\n\n /**\n * In case the request has a paymaster:\n * Validate paymaster has enough deposit.\n * Call paymaster.validatePaymasterUserOp.\n * Revert with proper FailedOp in case paymaster reverts.\n * Decrement paymaster's deposit\n */\n function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment)\n internal returns (bytes memory context, uint256 validationData) {\n unchecked {\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 verificationGasLimit = mUserOp.verificationGasLimit;\n require(verificationGasLimit > gasUsedByValidateAccountPrepayment, \"AA41 too little verificationGas\");\n uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment;\n\n address paymaster = mUserOp.paymaster;\n DepositInfo storage paymasterInfo = deposits[paymaster];\n uint256 deposit = paymasterInfo.deposit;\n if (deposit < requiredPreFund) {\n revert FailedOp(opIndex, \"AA31 paymaster deposit too low\");\n }\n paymasterInfo.deposit = uint112(deposit - requiredPreFund);\n try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){\n context = _context;\n validationData = _validationData;\n } catch Error(string memory revertReason) {\n revert FailedOp(opIndex, string.concat(\"AA33 reverted: \", revertReason));\n } catch {\n revert FailedOp(opIndex, \"AA33 reverted (or OOG)\");\n }\n }\n }\n\n /**\n * revert if either account validationData or paymaster validationData is expired\n */\n function _validateAccountAndPaymasterValidationData(uint256 opIndex, uint256 validationData, uint256 paymasterValidationData, address expectedAggregator) internal view {\n (address aggregator, bool outOfTimeRange) = _getValidationData(validationData);\n if (expectedAggregator != aggregator) {\n revert FailedOp(opIndex, \"AA24 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA22 expired or not due\");\n }\n //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.\n // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation)\n address pmAggregator;\n (pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);\n if (pmAggregator != address(0)) {\n revert FailedOp(opIndex, \"AA34 signature error\");\n }\n if (outOfTimeRange) {\n revert FailedOp(opIndex, \"AA32 paymaster expired or not due\");\n }\n }\n\n function _getValidationData(uint256 validationData) internal view returns (address aggregator, bool outOfTimeRange) {\n if (validationData == 0) {\n return (address(0), false);\n }\n ValidationData memory data = _parseValidationData(validationData);\n // solhint-disable-next-line not-rely-on-time\n outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;\n aggregator = data.aggregator;\n }\n\n /**\n * validate account and paymaster (if defined).\n * also make sure total validation doesn't exceed verificationGasLimit\n * this method is called off-chain (simulateValidation()) and on-chain (from handleOps)\n * @param opIndex the index of this userOp into the \"opInfos\" array\n * @param userOp the userOp to validate\n */\n function _validatePrepayment(uint256 opIndex, UserOperation calldata userOp, UserOpInfo memory outOpInfo)\n private returns (uint256 validationData, uint256 paymasterValidationData) {\n\n uint256 preGas = gasleft();\n MemoryUserOp memory mUserOp = outOpInfo.mUserOp;\n _copyUserOpToMemory(userOp, mUserOp);\n outOpInfo.userOpHash = getUserOpHash(userOp);\n\n // validate all numeric values in userOp are well below 128 bit, so they can safely be added\n // and multiplied without causing overflow\n uint256 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit |\n userOp.maxFeePerGas | userOp.maxPriorityFeePerGas;\n require(maxGasValues <= type(uint120).max, \"AA94 gas values overflow\");\n\n uint256 gasUsedByValidateAccountPrepayment;\n (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp);\n (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);\n\n if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {\n revert FailedOp(opIndex, \"AA25 invalid account nonce\");\n }\n\n //a \"marker\" where account opcode validation is done and paymaster opcode validation is about to start\n // (used only by off-chain simulateValidation)\n numberMarker();\n\n bytes memory context;\n if (mUserOp.paymaster != address(0)) {\n (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment);\n }\n unchecked {\n uint256 gasUsed = preGas - gasleft();\n\n if (userOp.verificationGasLimit < gasUsed) {\n revert FailedOp(opIndex, \"AA40 over verificationGasLimit\");\n }\n outOpInfo.prefund = requiredPreFund;\n outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);\n outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;\n }\n }\n\n /**\n * process post-operation.\n * called just after the callData is executed.\n * if a paymaster is defined and its validation returned a non-empty context, its postOp is called.\n * the excess amount is refunded to the account (or paymaster - if it was used in the request)\n * @param opIndex index in the batch\n * @param mode - whether is called from innerHandleOp, or outside (postOpReverted)\n * @param opInfo userOp fields and info collected during validation\n * @param context the context returned in validatePaymasterUserOp\n * @param actualGas the gas used so far by this user operation\n */\n function _handlePostOp(uint256 opIndex, IPaymaster.PostOpMode mode, UserOpInfo memory opInfo, bytes memory context, uint256 actualGas) private returns (uint256 actualGasCost) {\n uint256 preGas = gasleft();\n unchecked {\n address refundAddress;\n MemoryUserOp memory mUserOp = opInfo.mUserOp;\n uint256 gasPrice = getUserOpGasPrice(mUserOp);\n\n address paymaster = mUserOp.paymaster;\n if (paymaster == address(0)) {\n refundAddress = mUserOp.sender;\n } else {\n refundAddress = paymaster;\n if (context.length > 0) {\n actualGasCost = actualGas * gasPrice;\n if (mode != IPaymaster.PostOpMode.postOpReverted) {\n IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost);\n } else {\n // solhint-disable-next-line no-empty-blocks\n try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {}\n catch Error(string memory reason) {\n revert FailedOp(opIndex, string.concat(\"AA50 postOp reverted: \", reason));\n }\n catch {\n revert FailedOp(opIndex, \"AA50 postOp revert\");\n }\n }\n }\n }\n actualGas += preGas - gasleft();\n actualGasCost = actualGas * gasPrice;\n if (opInfo.prefund < actualGasCost) {\n revert FailedOp(opIndex, \"AA51 prefund below actualGasCost\");\n }\n uint256 refund = opInfo.prefund - actualGasCost;\n _incrementDeposit(refundAddress, refund);\n bool success = mode == IPaymaster.PostOpMode.opSucceeded;\n emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, success, actualGasCost, actualGas);\n } // unchecked\n }\n\n /**\n * the gas price this UserOp agrees to pay.\n * relayer/block builder might submit the TX with higher priorityFee, but the user should not\n */\n function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = mUserOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {\n assembly {offset := data}\n }\n\n function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {\n assembly {data := offset}\n }\n\n //place the NUMBER opcode in the code.\n // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the\n // account and paymaster.\n function numberMarker() internal view {\n assembly {mstore(0, number())}\n }\n}\n\n"
+ },
+ "contracts/core/Helpers.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\n/**\n * returned data from validateUserOp.\n * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`\n * @param aggregator - address(0) - the account validated the signature by itself.\n * address(1) - the account failed to validate the signature.\n * otherwise - this is an address of a signature aggregator that must be used to validate the signature.\n * @param validAfter - this UserOp is valid only after this timestamp.\n * @param validaUntil - this UserOp is valid only up to this timestamp.\n */\n struct ValidationData {\n address aggregator;\n uint48 validAfter;\n uint48 validUntil;\n }\n\n//extract sigFailed, validAfter, validUntil.\n// also convert zero validUntil to type(uint48).max\n function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {\n address aggregator = address(uint160(validationData));\n uint48 validUntil = uint48(validationData >> 160);\n if (validUntil == 0) {\n validUntil = type(uint48).max;\n }\n uint48 validAfter = uint48(validationData >> (48 + 160));\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n// intersect account and paymaster ranges.\n function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {\n ValidationData memory accountValidationData = _parseValidationData(validationData);\n ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);\n address aggregator = accountValidationData.aggregator;\n if (aggregator == address(0)) {\n aggregator = pmValidationData.aggregator;\n }\n uint48 validAfter = accountValidationData.validAfter;\n uint48 validUntil = accountValidationData.validUntil;\n uint48 pmValidAfter = pmValidationData.validAfter;\n uint48 pmValidUntil = pmValidationData.validUntil;\n\n if (validAfter < pmValidAfter) validAfter = pmValidAfter;\n if (validUntil > pmValidUntil) validUntil = pmValidUntil;\n return ValidationData(aggregator, validAfter, validUntil);\n }\n\n/**\n * helper to pack the return value for validateUserOp\n * @param data - the ValidationData to pack\n */\n function _packValidationData(ValidationData memory data) pure returns (uint256) {\n return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));\n }\n\n/**\n * helper to pack the return value for validateUserOp, when not using an aggregator\n * @param sigFailed - true for signature failure, false for success\n * @param validUntil last timestamp this UserOperation is valid (or zero for infinite)\n * @param validAfter first timestamp this UserOperation is valid\n */\n function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {\n return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));\n }\n\n/**\n * keccak function over calldata.\n * @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.\n */\n function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {\n assembly {\n let mem := mload(0x40)\n let len := data.length\n calldatacopy(mem, data.offset, len)\n ret := keccak256(mem, len)\n }\n }\n\n"
+ },
+ "contracts/core/NonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IEntryPoint.sol\";\n\n/**\n * nonce management functionality\n */\ncontract NonceManager is INonceManager {\n\n /**\n * The next valid sequence number for a given nonce key.\n */\n mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;\n\n function getNonce(address sender, uint192 key)\n public view override returns (uint256 nonce) {\n return nonceSequenceNumber[sender][key] | (uint256(key) << 64);\n }\n\n // allow an account to manually increment its own nonce.\n // (mainly so that during construction nonce can be made non-zero,\n // to \"absorb\" the gas cost of first nonce increment to 1st transaction (construction),\n // not to 2nd transaction)\n function incrementNonce(uint192 key) public override {\n nonceSequenceNumber[msg.sender][key]++;\n }\n\n /**\n * validate nonce uniqueness for this account.\n * called just after validateUserOp()\n */\n function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {\n\n uint192 key = uint192(nonce >> 64);\n uint64 seq = uint64(nonce);\n return nonceSequenceNumber[sender][key]++ == seq;\n }\n\n}\n"
+ },
+ "contracts/core/SenderCreator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/**\n * helper contract for EntryPoint, to call userOp.initCode from a \"neutral\" address,\n * which is explicitly not the entryPoint itself.\n */\ncontract SenderCreator {\n\n /**\n * call the \"initCode\" factory to create and return the sender account address\n * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata\n * @return sender the returned address of the created account, or zero address on failure.\n */\n function createSender(bytes calldata initCode) external returns (address sender) {\n address factory = address(bytes20(initCode[0 : 20]));\n bytes memory initCallData = initCode[20 :];\n bool success;\n /* solhint-disable no-inline-assembly */\n assembly {\n success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32)\n sender := mload(0)\n }\n if (!success) {\n sender = address(0);\n }\n }\n}\n"
+ },
+ "contracts/core/StakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\nimport \"../interfaces/IStakeManager.sol\";\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable not-rely-on-time */\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by a paymaster.\n */\nabstract contract StakeManager is IStakeManager {\n\n /// maps paymaster to their deposits and stakes\n mapping(address => DepositInfo) public deposits;\n\n /// @inheritdoc IStakeManager\n function getDepositInfo(address account) public view returns (DepositInfo memory info) {\n return deposits[account];\n }\n\n // internal method to return just the stake info\n function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) {\n DepositInfo storage depositInfo = deposits[addr];\n info.stake = depositInfo.stake;\n info.unstakeDelaySec = depositInfo.unstakeDelaySec;\n }\n\n /// return the deposit (for gas payment) of the account\n function balanceOf(address account) public view returns (uint256) {\n return deposits[account].deposit;\n }\n\n receive() external payable {\n depositTo(msg.sender);\n }\n\n function _incrementDeposit(address account, uint256 amount) internal {\n DepositInfo storage info = deposits[account];\n uint256 newAmount = info.deposit + amount;\n require(newAmount <= type(uint112).max, \"deposit overflow\");\n info.deposit = uint112(newAmount);\n }\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) public payable {\n _incrementDeposit(account, msg.value);\n DepositInfo storage info = deposits[account];\n emit Deposited(account, info.deposit);\n }\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 unstakeDelaySec) public payable {\n DepositInfo storage info = deposits[msg.sender];\n require(unstakeDelaySec > 0, \"must specify unstake delay\");\n require(unstakeDelaySec >= info.unstakeDelaySec, \"cannot decrease unstake time\");\n uint256 stake = info.stake + msg.value;\n require(stake > 0, \"no stake specified\");\n require(stake <= type(uint112).max, \"stake overflow\");\n deposits[msg.sender] = DepositInfo(\n info.deposit,\n true,\n uint112(stake),\n unstakeDelaySec,\n 0\n );\n emit StakeLocked(msg.sender, stake, unstakeDelaySec);\n }\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external {\n DepositInfo storage info = deposits[msg.sender];\n require(info.unstakeDelaySec != 0, \"not staked\");\n require(info.staked, \"already unstaking\");\n uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;\n info.withdrawTime = withdrawTime;\n info.staked = false;\n emit StakeUnlocked(msg.sender, withdrawTime);\n }\n\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external {\n DepositInfo storage info = deposits[msg.sender];\n uint256 stake = info.stake;\n require(stake > 0, \"No stake to withdraw\");\n require(info.withdrawTime > 0, \"must call unlockStake() first\");\n require(info.withdrawTime <= block.timestamp, \"Stake withdrawal is not due\");\n info.unstakeDelaySec = 0;\n info.withdrawTime = 0;\n info.stake = 0;\n emit StakeWithdrawn(msg.sender, withdrawAddress, stake);\n (bool success,) = withdrawAddress.call{value : stake}(\"\");\n require(success, \"failed to withdraw stake\");\n }\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external {\n DepositInfo storage info = deposits[msg.sender];\n require(withdrawAmount <= info.deposit, \"Withdraw amount too large\");\n info.deposit = uint112(info.deposit - withdrawAmount);\n emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);\n (bool success,) = withdrawAddress.call{value : withdrawAmount}(\"\");\n require(success, \"failed to withdraw\");\n }\n}\n"
+ },
+ "contracts/interfaces/IAccount.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\ninterface IAccount {\n\n /**\n * Validate user's signature and nonce\n * the entryPoint will make the call to the recipient only if this validation call returns successfully.\n * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).\n * This allows making a \"simulation call\" without a valid signature\n * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.\n *\n * @dev Must validate caller is the entryPoint.\n * Must validate the signature and nonce\n * @param userOp the operation that is about to be executed.\n * @param userOpHash hash of the user's request data. can be used as the basis for signature.\n * @param missingAccountFunds missing funds on the account's deposit in the entrypoint.\n * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.\n * The excess is left as a deposit in the entrypoint, for future calls.\n * can be withdrawn anytime using \"entryPoint.withdrawTo()\"\n * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.\n * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)\n external returns (uint256 validationData);\n}\n"
+ },
+ "contracts/interfaces/IAggregator.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * Aggregated Signatures validator.\n */\ninterface IAggregator {\n\n /**\n * validate aggregated signature.\n * revert if the aggregated signature does not match the given list of operations.\n */\n function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;\n\n /**\n * validate signature of a single userOp\n * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation\n * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.\n * @param userOp the userOperation received from the user.\n * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.\n * (usually empty, unless account and aggregator support some kind of \"multisig\"\n */\n function validateUserOpSignature(UserOperation calldata userOp)\n external view returns (bytes memory sigForUserOp);\n\n /**\n * aggregate multiple signatures into a single value.\n * This method is called off-chain to calculate the signature to pass with handleOps()\n * bundler MAY use optimized custom code perform this aggregation\n * @param userOps array of UserOperations to collect the signatures from.\n * @return aggregatedSignature the aggregated signature\n */\n function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);\n}\n"
+ },
+ "contracts/interfaces/IEntryPoint.sol": {
+ "content": "/**\n ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.\n ** Only one instance required on each chain.\n **/\n// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable avoid-low-level-calls */\n/* solhint-disable no-inline-assembly */\n/* solhint-disable reason-string */\n\nimport \"./UserOperation.sol\";\nimport \"./IStakeManager.sol\";\nimport \"./IAggregator.sol\";\nimport \"./INonceManager.sol\";\n\ninterface IEntryPoint is IStakeManager, INonceManager {\n\n /***\n * An event emitted after each successful request\n * @param userOpHash - unique identifier for the request (hash its entire content, except signature).\n * @param sender - the account that generates this request.\n * @param paymaster - if non-null, the paymaster that pays for this request.\n * @param nonce - the nonce value from the request.\n * @param success - true if the sender transaction succeeded, false if reverted.\n * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.\n * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).\n */\n event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);\n\n /**\n * account \"sender\" was deployed.\n * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.\n * @param sender the account that is deployed\n * @param factory the factory used to deploy this account (in the initCode)\n * @param paymaster the paymaster used by this UserOp\n */\n event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);\n\n /**\n * An event emitted if the UserOperation \"callData\" reverted with non-zero length\n * @param userOpHash the request unique identifier.\n * @param sender the sender of this request\n * @param nonce the nonce used in the request\n * @param revertReason - the return bytes from the (reverted) call to \"callData\".\n */\n event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);\n\n /**\n * an event emitted by handleOps(), before starting the execution loop.\n * any event emitted before this event, is part of the validation.\n */\n event BeforeExecution();\n\n /**\n * signature aggregator used by the following UserOperationEvents within this bundle.\n */\n event SignatureAggregatorChanged(address indexed aggregator);\n\n /**\n * a custom revert error of handleOps, to identify the offending op.\n * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.\n * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)\n * @param reason - revert reason\n * The string starts with a unique code \"AAmn\", where \"m\" is \"1\" for factory, \"2\" for account and \"3\" for paymaster issues,\n * so a failure can be attributed to the correct entity.\n * Should be caught in off-chain handleOps simulation and not happen on-chain.\n * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.\n */\n error FailedOp(uint256 opIndex, string reason);\n\n /**\n * error case when a signature aggregator fails to verify the aggregated signature it had created.\n */\n error SignatureValidationFailed(address aggregator);\n\n /**\n * Successful result from simulateValidation.\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n */\n error ValidationResult(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);\n\n /**\n * Successful result from simulateValidation, if the account returns a signature aggregator\n * @param returnInfo gas and time-range returned values\n * @param senderInfo stake information about the sender\n * @param factoryInfo stake information about the factory (if any)\n * @param paymasterInfo stake information about the paymaster (if any)\n * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)\n * bundler MUST use it to verify the signature, or reject the UserOperation\n */\n error ValidationResultWithAggregation(ReturnInfo returnInfo,\n StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,\n AggregatorStakeInfo aggregatorInfo);\n\n /**\n * return value of getSenderAddress\n */\n error SenderAddressResult(address sender);\n\n /**\n * return value of simulateHandleOp\n */\n error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);\n\n //UserOps handled, per aggregator\n struct UserOpsPerAggregator {\n UserOperation[] userOps;\n\n // aggregator address\n IAggregator aggregator;\n // aggregated signature\n bytes signature;\n }\n\n /**\n * Execute a batch of UserOperation.\n * no signature aggregator is used.\n * if any account requires an aggregator (that is, it returned an aggregator when\n * performing simulateValidation), then handleAggregatedOps() must be used instead.\n * @param ops the operations to execute\n * @param beneficiary the address to receive the fees\n */\n function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;\n\n /**\n * Execute a batch of UserOperation with Aggregators\n * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)\n * @param beneficiary the address to receive the fees\n */\n function handleAggregatedOps(\n UserOpsPerAggregator[] calldata opsPerAggregator,\n address payable beneficiary\n ) external;\n\n /**\n * generate a request Id - unique identifier for this request.\n * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.\n */\n function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);\n\n /**\n * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.\n * @dev this method always revert. Successful result is ValidationResult error. other errors are failures.\n * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.\n * @param userOp the user operation to validate.\n */\n function simulateValidation(UserOperation calldata userOp) external;\n\n /**\n * gas and return values during simulation\n * @param preOpGas the gas used for validation (including preValidationGas)\n * @param prefund the required prefund for this operation\n * @param sigFailed validateUserOp's (or paymaster's) signature check failed\n * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)\n * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)\n */\n struct ReturnInfo {\n uint256 preOpGas;\n uint256 prefund;\n bool sigFailed;\n uint48 validAfter;\n uint48 validUntil;\n bytes paymasterContext;\n }\n\n /**\n * returned aggregated signature info.\n * the aggregator returned by the account, and its current stake.\n */\n struct AggregatorStakeInfo {\n address aggregator;\n StakeInfo stakeInfo;\n }\n\n /**\n * Get counterfactual sender address.\n * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.\n * this method always revert, and returns the address in SenderAddressResult error\n * @param initCode the constructor code to be passed into the UserOperation.\n */\n function getSenderAddress(bytes memory initCode) external;\n\n\n /**\n * simulate full execution of a UserOperation (including both validation and target execution)\n * this method will always revert with \"ExecutionResult\".\n * it performs full validation of the UserOperation, but ignores signature error.\n * an optional target address is called after the userop succeeds, and its value is returned\n * (before the entire call is reverted)\n * Note that in order to collect the the success/failure of the target call, it must be executed\n * with trace enabled to track the emitted events.\n * @param op the UserOperation to simulate\n * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult\n * are set to the return from that call.\n * @param targetCallData callData to pass to target address\n */\n function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;\n}\n\n"
+ },
+ "contracts/interfaces/INonceManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\ninterface INonceManager {\n\n /**\n * Return the next nonce for this sender.\n * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)\n * But UserOp with different keys can come with arbitrary order.\n *\n * @param sender the account address\n * @param key the high 192 bit of the nonce\n * @return nonce a full nonce to pass for next UserOp with this sender.\n */\n function getNonce(address sender, uint192 key)\n external view returns (uint256 nonce);\n\n /**\n * Manually increment the nonce of the sender.\n * This method is exposed just for completeness..\n * Account does NOT need to call it, neither during validation, nor elsewhere,\n * as the EntryPoint will update the nonce regardless.\n * Possible use-case is call it with various keys to \"initialize\" their nonces to one, so that future\n * UserOperations will not pay extra for the first transaction with a given key.\n */\n function incrementNonce(uint192 key) external;\n}\n"
+ },
+ "contracts/interfaces/IPaymaster.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\nimport \"./UserOperation.sol\";\n\n/**\n * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.\n * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.\n */\ninterface IPaymaster {\n\n enum PostOpMode {\n opSucceeded, // user op succeeded\n opReverted, // user op reverted. still has to pay for gas.\n postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.\n }\n\n /**\n * payment validation: check if paymaster agrees to pay.\n * Must verify sender is the entryPoint.\n * Revert to reject this request.\n * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)\n * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.\n * @param userOp the user operation\n * @param userOpHash hash of the user's request data.\n * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)\n * @return context value to send to a postOp\n * zero length to signify postOp is not required.\n * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation\n * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,\n * otherwise, an address of an \"authorizer\" contract.\n * <6-byte> validUntil - last timestamp this operation is valid. 0 for \"indefinite\"\n * <6-byte> validAfter - first timestamp this operation is valid\n * Note that the validation code cannot use block.timestamp (or block.number) directly.\n */\n function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)\n external returns (bytes memory context, uint256 validationData);\n\n /**\n * post-operation handler.\n * Must verify sender is the entryPoint\n * @param mode enum with the following options:\n * opSucceeded - user operation succeeded.\n * opReverted - user op reverted. still has to pay for gas.\n * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.\n * Now this is the 2nd call, after user's op was deliberately reverted.\n * @param context - the context value returned by validatePaymasterUserOp\n * @param actualGasCost - actual gas used so far (without this postOp call).\n */\n function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external;\n}\n"
+ },
+ "contracts/interfaces/IStakeManager.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.12;\n\n/**\n * manage deposits and stakes.\n * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)\n * stake is value locked for at least \"unstakeDelay\" by the staked entity.\n */\ninterface IStakeManager {\n\n event Deposited(\n address indexed account,\n uint256 totalDeposit\n );\n\n event Withdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /// Emitted when stake or unstake delay are modified\n event StakeLocked(\n address indexed account,\n uint256 totalStaked,\n uint256 unstakeDelaySec\n );\n\n /// Emitted once a stake is scheduled for withdrawal\n event StakeUnlocked(\n address indexed account,\n uint256 withdrawTime\n );\n\n event StakeWithdrawn(\n address indexed account,\n address withdrawAddress,\n uint256 amount\n );\n\n /**\n * @param deposit the entity's deposit\n * @param staked true if this entity is staked.\n * @param stake actual amount of ether staked for this entity.\n * @param unstakeDelaySec minimum delay to withdraw the stake.\n * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked\n * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)\n * and the rest fit into a 2nd cell.\n * 112 bit allows for 10^15 eth\n * 48 bit for full timestamp\n * 32 bit allows 150 years for unstake delay\n */\n struct DepositInfo {\n uint112 deposit;\n bool staked;\n uint112 stake;\n uint32 unstakeDelaySec;\n uint48 withdrawTime;\n }\n\n //API struct used by getStakeInfo and simulateValidation\n struct StakeInfo {\n uint256 stake;\n uint256 unstakeDelaySec;\n }\n\n /// @return info - full deposit information of given account\n function getDepositInfo(address account) external view returns (DepositInfo memory info);\n\n /// @return the deposit (for gas payment) of the account\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * add to the deposit of the given account\n */\n function depositTo(address account) external payable;\n\n /**\n * add to the account's stake - amount and delay\n * any pending unstake is first cancelled.\n * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.\n */\n function addStake(uint32 _unstakeDelaySec) external payable;\n\n /**\n * attempt to unlock the stake.\n * the value can be withdrawn (using withdrawStake) after the unstake delay.\n */\n function unlockStake() external;\n\n /**\n * withdraw from the (unlocked) stake.\n * must first call unlockStake and wait for the unstakeDelay to pass\n * @param withdrawAddress the address to send withdrawn value.\n */\n function withdrawStake(address payable withdrawAddress) external;\n\n /**\n * withdraw from the deposit.\n * @param withdrawAddress the address to send withdrawn value.\n * @param withdrawAmount the amount to withdraw.\n */\n function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;\n}\n"
+ },
+ "contracts/interfaces/UserOperation.sol": {
+ "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.12;\n\n/* solhint-disable no-inline-assembly */\n\nimport {calldataKeccak} from \"../core/Helpers.sol\";\n\n/**\n * User Operation struct\n * @param sender the sender account of this request.\n * @param nonce unique value the sender uses to verify it is not a replay.\n * @param initCode if set, the account contract will be created by this constructor/\n * @param callData the method call to execute on this account.\n * @param callGasLimit the gas limit passed to the callData method call.\n * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.\n * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.\n * @param maxFeePerGas same as EIP-1559 gas parameter.\n * @param maxPriorityFeePerGas same as EIP-1559 gas parameter.\n * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender.\n * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.\n */\n struct UserOperation {\n\n address sender;\n uint256 nonce;\n bytes initCode;\n bytes callData;\n uint256 callGasLimit;\n uint256 verificationGasLimit;\n uint256 preVerificationGas;\n uint256 maxFeePerGas;\n uint256 maxPriorityFeePerGas;\n bytes paymasterAndData;\n bytes signature;\n }\n\n/**\n * Utility functions helpful when working with UserOperation structs.\n */\nlibrary UserOperationLib {\n\n function getSender(UserOperation calldata userOp) internal pure returns (address) {\n address data;\n //read sender from userOp, which is first userOp member (saves 800 gas...)\n assembly {data := calldataload(userOp)}\n return address(uint160(data));\n }\n\n //relayer/block builder might submit the TX with higher priorityFee, but the user should not\n // pay above what he signed for.\n function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {\n unchecked {\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n if (maxFeePerGas == maxPriorityFeePerGas) {\n //legacy mode (for networks that don't support basefee opcode)\n return maxFeePerGas;\n }\n return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);\n }\n }\n\n function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {\n address sender = getSender(userOp);\n uint256 nonce = userOp.nonce;\n bytes32 hashInitCode = calldataKeccak(userOp.initCode);\n bytes32 hashCallData = calldataKeccak(userOp.callData);\n uint256 callGasLimit = userOp.callGasLimit;\n uint256 verificationGasLimit = userOp.verificationGasLimit;\n uint256 preVerificationGas = userOp.preVerificationGas;\n uint256 maxFeePerGas = userOp.maxFeePerGas;\n uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;\n bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);\n\n return abi.encode(\n sender, nonce,\n hashInitCode, hashCallData,\n callGasLimit, verificationGasLimit, preVerificationGas,\n maxFeePerGas, maxPriorityFeePerGas,\n hashPaymasterAndData\n );\n }\n\n function hash(UserOperation calldata userOp) internal pure returns (bytes32) {\n return keccak256(pack(userOp));\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n"
+ },
+ "contracts/utils/Exec.sol": {
+ "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.5 <0.9.0;\n\n// solhint-disable no-inline-assembly\n\n/**\n * Utility functions helpful when making different kinds of contract calls in Solidity.\n */\nlibrary Exec {\n\n function call(\n address to,\n uint256 value,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function staticcall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal view returns (bool success) {\n assembly {\n success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n function delegateCall(\n address to,\n bytes memory data,\n uint256 txGas\n ) internal returns (bool success) {\n assembly {\n success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)\n }\n }\n\n // get returned data from last call or calldelegate\n function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {\n assembly {\n let len := returndatasize()\n if gt(len, maxLen) {\n len := maxLen\n }\n let ptr := mload(0x40)\n mstore(0x40, add(ptr, add(len, 0x20)))\n mstore(ptr, len)\n returndatacopy(add(ptr, 0x20), 0, len)\n returnData := ptr\n }\n }\n\n // revert with explicit byte array (probably reverted info from call)\n function revertWithData(bytes memory returnData) internal pure {\n assembly {\n revert(add(returnData, 32), mload(returnData))\n }\n }\n\n function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {\n bool success = call(to,0,data,gasleft());\n if (!success) {\n revertWithData(getReturnData(maxLen));\n }\n }\n}\n"
+ }
+ },
+ "settings": {
+ "optimizer": {
+ "enabled": true,
+ "runs": 1000000
+ },
+ "viaIR": true,
+ "outputSelection": {
+ "*": {
+ "*": [
+ "abi",
+ "evm.bytecode",
+ "evm.deployedBytecode",
+ "evm.methodIdentifiers",
+ "metadata"
+ ],
+ "": [
+ "ast"
+ ]
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/ERCS/erc-4337.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/ERCS/erc-4337.md
new file mode 100644
index 000000000..ef0e92370
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/ERCS/erc-4337.md
@@ -0,0 +1,1017 @@
+---
+eip: 4337
+title: Account Abstraction Using Alt Mempool
+description: An account abstraction proposal which completely avoids consensus-layer protocol changes, instead relying on higher-layer infrastructure.
+author: Vitalik Buterin (@vbuterin), Yoav Weiss (@yoavw), Dror Tirosh (@drortirosh), Shahaf Nacson (@shahafn), Alex Forshtat (@forshtat), Kristof Gazso (@kristofgazso), Tjaden Hess (@tjade273)
+discussions-to: https://ethereum-magicians.org/t/erc-4337-account-abstraction-via-entry-point-contract-specification/7160
+status: Draft
+type: Standards Track
+category: ERC
+created: 2021-09-29
+requires: 7562
+---
+
+## Abstract
+
+An account abstraction proposal which completely avoids the need for consensus-layer protocol changes. Instead of adding new protocol features and changing the bottom-layer transaction type, this proposal instead introduces a higher-layer pseudo-transaction object called a `UserOperation`. Users send `UserOperation` objects into a separate mempool. A special class of actor called bundlers package up a set of these objects into a transaction making a `handleOps` call to a special contract, and that transaction then gets included in a block.
+
+## Motivation
+
+See also `https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020` and the links therein for historical work and motivation, and [EIP-2938](./eip-2938.md) for a consensus layer proposal for implementing the same goal.
+
+This proposal takes a different approach, avoiding any adjustments to the consensus layer. It seeks to achieve the following goals:
+
+- **Achieve the key goal of account abstraction**: allow users to use smart contract wallets containing arbitrary verification logic instead of EOAs as their primary account. Completely remove any need at all for users to also have EOAs (as status quo SC wallets and [EIP-3074](./eip-3074.md) both require)
+- **Decentralization**
+ - Allow any bundler (think: block builder) to participate in the process of including account-abstracted user operations
+ - Work with all activity happening over a public mempool; users do not need to know the direct communication addresses (eg. IP, onion) of any specific actors
+ - Avoid trust assumptions on bundlers
+- **Do not require any Ethereum consensus changes**: Ethereum consensus layer development is focusing on the merge and later on scalability-oriented features, and there may not be any opportunity for further protocol changes for a long time. Hence, to increase the chance of faster adoption, this proposal avoids Ethereum consensus changes.
+- **Try to support other use cases**
+ - Privacy-preserving applications
+ - Atomic multi-operations (similar goal to [EIP-3074])
+ - Pay tx fees with [ERC-20](./erc-20.md) tokens, allow developers to pay fees for their users, and [EIP-3074]-like **sponsored transaction** use cases more generally
+ - Support aggregated signature (e.g. BLS)
+
+## Specification
+
+### Definitions
+
+- **UserOperation** - a structure that describes a transaction to be sent on behalf of a user. To avoid confusion, it is not named "transaction".
+ - Like a transaction, it contains "sender", "to", "calldata", "maxFeePerGas", "maxPriorityFee", "signature", "nonce"
+ - unlike a transaction, it contains several other fields, described below
+ - also, the "signature" field usage is not defined by the protocol, but by each account implementation
+- **Sender** - the account contract sending a user operation.
+- **EntryPoint** - a singleton contract to execute bundles of UserOperations. Bundlers/Clients whitelist the supported entrypoint.
+- **Bundler** - a node (block builder) that can handle UserOperations,
+ create a valid an EntryPoint.handleOps() transaction,
+ and add it to the block while it is still valid.
+ This can be achieved by a number of ways:
+ - Bundler can act as a block builder itself
+ - If the bundler is not a block builder, it MUST work with the block building infrastructure such as `mev-boost` or
+ other kind of PBS (proposer-builder separation)
+ - The `bundler` can also rely on an experimental `eth_sendRawTransactionConditional` RPC API if it is available.
+- **Aggregator** - a helper contract trusted by accounts to validate an aggregated signature. Bundlers/Clients whitelist the supported aggregators.
+
+To avoid Ethereum consensus changes, we do not attempt to create new transaction types for account-abstracted transactions. Instead, users package up the action they want their account to take in a struct named `UserOperation`:
+
+| Field | Type | Description |
+| ------------------------------- | --------- | ----------------------------------------------------------------------------- |
+| `sender` | `address` | The account making the operation |
+| `nonce` | `uint256` | Anti-replay parameter (see "Semi-abstracted Nonce Support" ) |
+| `factory` | `address` | account factory, only for new accounts |
+| `factoryData` | `bytes` | data for account factory (only if account factory exists) |
+| `callData` | `bytes` | The data to pass to the `sender` during the main execution call |
+| `callGasLimit` | `uint256` | The amount of gas to allocate the main execution call |
+| `verificationGasLimit` | `uint256` | The amount of gas to allocate for the verification step |
+| `preVerificationGas` | `uint256` | Extra gas to pay the bunder |
+| `maxFeePerGas` | `uint256` | Maximum fee per gas (similar to [EIP-1559](./eip-1559.md) `max_fee_per_gas`) |
+| `maxPriorityFeePerGas` | `uint256` | Maximum priority fee per gas (similar to EIP-1559 `max_priority_fee_per_gas`) |
+| `paymaster` | `address` | Address of paymaster contract, (or empty, if account pays for itself) |
+| `paymasterVerificationGasLimit` | `uint256` | The amount of gas to allocate for the paymaster validation code |
+| `paymasterPostOpGasLimit` | `uint256` | The amount of gas to allocate for the paymaster post-operation code |
+| `paymasterData` | `bytes` | Data for paymaster (only if paymaster exists) |
+| `signature` | `bytes` | Data passed into the account to verify authorization |
+
+Users send `UserOperation` objects to a dedicated user operation mempool. The are not concerned with the packed version.
+A specialized class of actors called **bundlers** (either block builders running special-purpose code, or users that can relay transactions to block builders eg. through a bundle marketplace such as Flashbots that can guarantee next-block-or-never inclusion) listen in on the user operation mempool, and create **bundle transactions**. A bundle transaction packages up multiple `UserOperation` objects into a single `handleOps` call to a pre-published global **entry point contract**.
+
+To prevent replay attacks (both cross-chain and multiple `EntryPoint` implementations), the `signature` should depend on `chainid` and the `EntryPoint` address.
+
+When passed to on-chain contacts (the EntryPoint contract, and then to account and paymaster), a packed version of the above structure is used:
+
+| Field | Type | Description |
+| -------------------- | --------- | ---------------------------------------------------------------------- |
+| `sender` | `address` | |
+| `nonce` | `uint256` | |
+| `initCode` | `bytes` | concatenation of factory address and factoryData (or empty) |
+| `callData` | `bytes` | |
+| `accountGasLimits` | `bytes32` | concatenation of verificationGas (16 bytes) and callGas (16 bytes) |
+| `preVerificationGas` | `uint256` | |
+| `gasFees` | `bytes32` | concatenation of maxPriorityFee (16 bytes) and maxFeePerGas (16 bytes) |
+| `paymasterAndData` | `bytes` | concatenation of paymaster fields (or empty) |
+| `signature` | `bytes` | |
+
+The core interface of the entry point contract is as follows:
+
+```solidity
+function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary);
+
+function handleAggregatedOps(
+ UserOpsPerAggregator[] calldata opsPerAggregator,
+ address payable beneficiary
+);
+
+struct UserOpsPerAggregator {
+ PackedUserOperation[] userOps;
+ IAggregator aggregator;
+ bytes signature;
+}
+```
+
+The core interface required for an account to have is:
+
+```solidity
+interface IAccount {
+ function validateUserOp
+ (PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
+ external returns (uint256 validationData);
+}
+```
+
+The `userOpHash` is a hash over the userOp (except signature), entryPoint and chainId.
+
+The account:
+
+- MUST validate the caller is a trusted EntryPoint
+- If the account does not support signature aggregation, it MUST validate the signature is a valid signature of the `userOpHash`, and
+ SHOULD return SIG_VALIDATION_FAILED (and not revert) on signature mismatch. Any other error MUST revert.
+- MUST pay the entryPoint (caller) at least the "missingAccountFunds" (which might be zero, in case current account's deposit is high enough)
+- The account MAY pay more than this minimum, to cover future transactions (it can always issue `withdrawTo` to retrieve it)
+- The return value MUST be packed of `authorizer`, `validUntil` and `validAfter` timestamps.
+ - authorizer - 0 for valid signature, 1 to mark signature failure. Otherwise, an address of an authorizer contract. This ERC defines "signature aggregator" as authorizer.
+ - `validUntil` is 6-byte timestamp value, or zero for "infinite". The UserOp is valid only up to this time.
+ - `validAfter` is 6-byte timestamp. The UserOp is valid only after this time.
+
+An account that works with aggregated signature, should return its signature aggregator address in the "sigAuthorizer" return value of validateUserOp.
+It MAY ignore the signature field.
+
+The account MAY implement the interface `IAccountExecute`
+
+```solidity
+interface IAccountExecute {
+ function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external;
+}
+```
+
+This method will be called by the entryPoint with the current UserOperation, instead of executing the `callData` itself on the account.
+
+The core interface required by an aggregator is:
+
+```solidity
+interface IAggregator {
+
+ function validateUserOpSignature(PackedUserOperation calldata userOp)
+ external view returns (bytes memory sigForUserOp);
+
+ function aggregateSignatures(PackedUserOperation[] calldata userOps) external view returns (bytes memory aggregatesSignature);
+
+ function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) view external;
+}
+```
+
+- If an account uses an aggregator (returns it from validateUserOp), then its address is returned by `simulateValidation()` (in `aggregatorInfo`)
+- To accept the UserOp, the bundler must call **validateUserOpSignature()** to validate the userOp's signature.
+- **aggregateSignatures()** must aggregate all UserOp signature into a single value.
+- Note that the above methods are helper method for the bundler. The bundler MAY use a native library to perform the same validation and aggregation logic.
+- **validateSignatures()** MUST validate the aggregated signature matches for all UserOperations in the array, and revert otherwise.
+ This method is called on-chain by `handleOps()`
+
+#### Semi-abstracted Nonce Support
+
+In Ethereum protocol, the sequential transaction `nonce` value is used as a replay protection method as well as to
+determine the valid order of transaction being included in blocks.
+
+It also contributes to the transaction hash uniqueness, as a transaction by the same sender with the same
+nonce may not be included in the chain twice.
+
+However, requiring a single sequential `nonce` value is limiting the senders' ability to define their custom logic
+with regard to transaction ordering and replay protection.
+
+Instead of sequential `nonce` we implement a nonce mechanism that uses a single `uint256` nonce value in the `UserOperation`,
+but treats it as two values:
+
+- 192-bit "key"
+- 64-bit "sequence"
+
+These values are represented on-chain in the `EntryPoint` contract.
+We define the following method in the `EntryPoint` interface to expose these values:
+
+```solidity
+function getNonce(address sender, uint192 key) external view returns (uint256 nonce);
+```
+
+For each `key` the `sequence` is validated and incremented sequentially and monotonically by the `EntryPoint` for
+each UserOperation, however a new key can be introduced with an arbitrary value at any point.
+
+This approach maintains the guarantee of `UserOperation` hash uniqueness on-chain on the protocol level while allowing
+wallets to implement any custom logic they may need operating on a 192-bit "key" field, while fitting the 32 byte word.
+
+##### Reading and validating the nonce
+
+When preparing the UserOp clients may make a view call to this method to determine a valid value for the `nonce` field.
+
+Bundler's validation of a UserOp should start with `getNonce` to ensure the transaction has a valid `nonce` field.
+
+If the bundler is willing to accept multiple UserOperations by the same sender into their mempool,
+this bundler is supposed to track the `key` and `sequence` pair of the UserOperations already added in the mempool.
+
+##### Usage examples
+
+1. Classic sequential nonce.
+
+ In order to require the wallet to have classic, sequential nonce, the validation function should perform:
+
+ ```solidity
+ require(userOp.nonce> 64;
+ if (sig == ADMIN_METHODSIG) {
+ require(key == ADMIN_KEY, "wrong nonce-key for admin operation");
+ } else {
+ require(key == 0, "wrong nonce-key for normal operation");
+ }
+ ```
+
+#### Using signature aggregators
+
+An account signifies it uses signature aggregation returning its address from `validateUserOp`.
+During `simulateValidation`, this aggregator is returned as part of the `aggregatorInfo` struct.
+
+The bundler should first accept the aggregator (validate its stake info and that it is not throttled/banned)
+Then it MUST verify the userOp using `aggregator.validateUserOpSignature()`. This method returned an alternate signature (usually empty) that should be used during bundling.
+The bundler MUST call `validateUserOp` a second time on the account with the UserOperation using that returned signature.
+
+Signature aggregator MUST be staked.
+Bundlers MAY throttle down and ban aggregators in case they take too much resources (or revert) when the above methods are called in view mode, or if the signature aggregation fails.
+
+### Required entry point contract functionality
+
+There are 2 separate entry point methods: `handleOps` and `handleAggregatedOps`
+
+- `handleOps` handle userOps of accounts that don't require any signature aggregator.
+- `handleAggregatedOps` can handle a batch that contains userOps of multiple aggregators (and also requests without any aggregator)
+- `handleAggregatedOps` performs the same logic below as `handleOps`, but it must transfer the correct aggregator to each userOp, and also must call `validateSignatures` on each aggregator before doing all the per-account validation.
+ The entry point's `handleOps` function must perform the following steps (we first describe the simpler non-paymaster case). It must make two loops, the **verification loop** and the **execution loop**. In the verification loop, the `handleOps` call must perform the following steps for each `UserOperation`:
+
+- **Create the account if it does not yet exist**, using the initcode provided in the `UserOperation`. If the account does not exist, _and_ the initcode is empty, or does not deploy a contract at the "sender" address, the call must fail.
+- calculate the maximum possible fee the account needs to pay (based on validation and call gas limits, and current gas values)
+- calculate the fee the account must add to its "deposit" in the EntryPoint
+- **Call `validateUserOp` on the account**, passing in the `UserOperation`, its hash and the required fee. The account should verify the operation's signature, and pay the fee if the account considers the operation valid. If any `validateUserOp` call fails, `handleOps` must skip execution of at least that operation, and may revert entirely.
+- Validate the account's deposit in the entryPoint is high enough to cover the max possible cost (cover the already-done verification and max execution gas)
+
+In the execution loop, the `handleOps` call must perform the following steps for each `UserOperation`:
+
+- **Call the account with the `UserOperation`'s calldata**. It's up to the account to choose how to parse the calldata; an expected workflow is for the account to have an `execute` function that parses the remaining calldata as a series of one or more calls that the account should make.
+- If the calldata starts with the methodsig `IAccountExecute.executeUserOp`, then the EntryPoint must build a calldata by encoding `executeUserOp(userOp,userOpHash)` and call the account using that calldata.
+- After the call, refund the account's deposit with the excess gas cost that was pre-charged.\
+ A penalty of `10%` (`UNUSED_GAS_PENALTY_PERCENT`) is applied on the amount of gas that is refunded.\
+ This penalty is necessary to prevent the UserOps from reserving large parts of the gas space in the bundle but leaving it unused and preventing the bundler from including other UserOperations.
+- After the execution of all calls, pay the collected fees from all UserOperations to the bundler's provided address
+
+
+
+Before accepting a `UserOperation`, bundlers should use an RPC method to locally call the `simulateValidation` function on the entry point, to verify that the signature is correct and the operation actually pays fees; see the [Simulation section below](#simulation) for details.
+A node/bundler SHOULD drop (not add to the mempool) a `UserOperation` that fails the validation
+
+### Extension: paymasters
+
+We extend the entry point logic to support **paymasters** that can sponsor transactions for other users. This feature can be used to allow application developers to subsidize fees for their users, allow users to pay fees with [ERC-20](./erc-20.md) tokens and many other use cases. When the paymasterAndData field in the UserOp is not empty, the entry point implements a different flow for that UserOperation:
+
+
+
+During the verification loop, in addition to calling `validateUserOp`, the `handleOps` execution also must check that the paymaster has enough ETH deposited with the entry point to pay for the operation, and then call `validatePaymasterUserOp` on the paymaster to verify that the paymaster is willing to pay for the operation. Note that in this case, the `validateUserOp` is called with a `missingAccountFunds` of 0 to reflect that the account's deposit is not used for payment for this userOp.
+
+If the paymaster's validatePaymasterUserOp returns a "context", then `handleOps` must call `postOp` on the paymaster after making the main execution call.
+
+Maliciously crafted paymasters _can_ DoS the system. To prevent this, we use a reputation system. paymaster must either limit its storage usage, or have a stake. see the [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details.
+
+The paymaster interface is as follows:
+
+```solidity
+function validatePaymasterUserOp
+ (PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)
+ external returns (bytes memory context, uint256 validationData);
+
+function postOp
+ (PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas)
+ external;
+
+enum PostOpMode {
+ opSucceeded, // user op succeeded
+ opReverted, // user op reverted. still has to pay for gas.
+ postOpReverted // Regardless of the UserOp call status, the postOp reverted, and caused both executions to revert.
+}
+```
+
+The EntryPoint must implement the following API to let entities like paymasters to have a stake, and thus have more flexibility in their storage access (see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details.)
+
+```solidity
+// add a stake to the calling entity
+function addStake(uint32 _unstakeDelaySec) external payable
+
+// unlock the stake (must wait unstakeDelay before can withdraw)
+function unlockStake() external
+
+// withdraw the unlocked stake
+function withdrawStake(address payable withdrawAddress) external
+```
+
+The paymaster must also have a deposit, which the entry point will charge UserOperation costs from.
+The deposit (for paying gas fees) is separate from the stake (which is locked).
+
+The EntryPoint must implement the following interface to allow paymasters (and optionally accounts) manage their deposit:
+
+```c++
+// return the deposit of an account
+function balanceOf(address account) public view returns (uint256)
+
+// add to the deposit of the given account
+function depositTo(address account) public payable
+
+// withdraw from the deposit of the current account
+function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external
+```
+
+### Client behavior upon receiving a UserOperation
+
+When a client receives a `UserOperation`, it must first run some basic sanity checks, namely that:
+
+- Either the `sender` is an existing contract, or the `initCode` is not empty (but not both)
+- If `initCode` is not empty, parse its first 20 bytes as a factory address. Record whether the factory is staked, in case the later simulation indicates that it needs to be. If the factory accesses global state, it must be staked - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details.
+- The `verificationGasLimit` is sufficiently low (`<= MAX_VERIFICATION_GAS`) and the `preVerificationGas` is sufficiently high (enough to pay for the calldata gas cost of serializing the `UserOperation` plus `PRE_VERIFICATION_OVERHEAD_GAS`)
+- The `paymasterAndData` is either empty, or start with the **paymaster** address, which is a contract that (i) currently has nonempty code on chain, (ii) has a sufficient deposit to pay for the UserOperation, and (iii) is not currently banned. During simulation, the paymaster's stake is also checked, depending on its storage usage - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details.
+- The callgas is at least the cost of a `CALL` with non-zero value.
+- The `maxFeePerGas` and `maxPriorityFeePerGas` are above a configurable minimum value that the client is willing to accept. At the minimum, they are sufficiently high to be included with the current `block.basefee`.
+- The sender doesn't have another `UserOperation` already present in the pool (or it replaces an existing entry with the same sender and nonce, with a higher `maxPriorityFeePerGas` and an equally increased `maxFeePerGas`). Only one `UserOperation` per sender may be included in a single batch. A sender is exempt from this rule and may have multiple `UserOperations` in the pool and in a batch if it is staked (see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) below), but this exception is of limited use to normal accounts.
+
+If the `UserOperation` object passes these sanity checks, the client must next run the first op simulation, and if the simulation succeeds, the client must add the op to the pool. A second simulation must also happen during bundling to make sure the UserOperation is still valid.
+
+### Simulation
+
+#### Simulation Rationale
+
+In order to add a UserOperation into the mempool (and later to add it into a bundle) we need to "simulate" its validation to make sure it is valid, and that it is capable of paying for its own execution.
+In addition, we need to verify that the same will hold true when executed on-chain.
+For this purpose, a UserOperation is not allowed to access any information that might change between simulation and execution, such as current block time, number, hash etc.
+In addition, a UserOperation is only allowed to access data related to this sender address: Multiple UserOperations should not access the same storage, so that it is impossible to invalidate a large number of UserOperations with a single state change.
+There are 3 special contracts that interact with the account: the factory (initCode) that deploys the contract, the paymaster that can pay for the gas, and signature aggregator (described later)
+Each of these contracts is also restricted in its storage access, to make sure UserOperation validations are isolated.
+
+#### Specification:
+
+To simulate a `UserOperation` validation, the client makes a view call to `simulateValidation(userop)`.
+
+The EntryPoint itself does not implement the simulation methods. Instead, when making the simulation view call,
+The bundler should provide the alternate EntryPointSimulations code, which extends the EntryPoint with the simulation methods.
+
+The simulation core methods:
+
+```solidity
+
+struct ValidationResult {
+ ReturnInfo returnInfo;
+ StakeInfo senderInfo;
+ StakeInfo factoryInfo;
+ StakeInfo paymasterInfo;
+ AggregatorStakeInfo aggregatorInfo;
+}
+
+function simulateValidation(PackedUserOperation calldata userOp)
+external returns (ValidationResult memory);
+
+struct ReturnInfo {
+ uint256 preOpGas;
+ uint256 prefund;
+ uint256 accountValidationData;
+ uint256 paymasterValidationData;
+ bytes paymasterContext;
+}
+
+struct AggregatorStakeInfo {
+ address aggregator;
+ StakeInfo stakeInfo;
+}
+
+struct StakeInfo {
+ uint256 stake;
+ uint256 unstakeDelaySec;
+}
+
+
+```
+
+This method returns `ValidationResult` or revert on validation failure.
+The node should drop the UserOperation if the simulation fails (either by revert or by "signature failure")
+
+The simulated call performs the full validation, by calling:
+
+1. If `initCode` is present, create the account.
+2. `account.validateUserOp`.
+3. if specified a paymaster: `paymaster.validatePaymasterUserOp`.
+
+The simulateValidation should validate the return value (validationData) returned by the account's `validateUserOp` and paymaster's `validatePaymasterUserOp`.
+The account MAY return an aggregator. See [Using Signature Aggregator](#using-signature-aggregators)
+The paymaster MUST return either "0" (success) or SIG_VALIDATION_FAILED for aggregator, and not an address.
+Either return value may contain a "validAfter" and "validUntil" timestamps, which is the time-range that this UserOperation is valid on-chain.
+A node MAY drop a UserOperation if it expires too soon (e.g. wouldn't make it to the next block) by either the account or paymaster.
+If the `ValidationResult` includes `sigFail`, the client SHOULD drop the `UserOperation`.
+
+In order to prevent DoS attack on bundlers, they must make sure the validation methods above pass the validation rules, which constraint their usage of opcodes and storage.
+For the complete procedure see [ERC-7562](./erc-7562.md)
+
+#### Alternative Mempools
+
+The simulation rules above are strict and prevent the ability of paymasters and signature aggregators to grief the system.
+However, there might be use-cases where specific paymasters (and signature aggregators) can be validated
+(through manual auditing) and verified that they cannot cause any problem, while still require relaxing of the opcode rules.
+A bundler cannot simply "whitelist" request from a specific paymaster: if that paymaster is not accepted by all
+bundlers, then its support will be sporadic at best.
+Instead, we introduce the term "alternate mempool": a modified validation rules, and procedure of propagating them to other bundlers.
+
+The procedure of using alternate mempools is defined in [ERC-7562](./erc-7562.md#Alt-mempools-rules)
+
+### Bundling
+
+During bundling, the client should:
+
+- Exclude UserOps that access any sender address of another UserOp in the same batch.
+- Exclude UserOps that access any address created by another UserOp validation in the same batch (via a factory).
+- For each paymaster used in the batch, keep track of the balance while adding UserOps. Ensure that it has sufficient deposit to pay for all the UserOps that use it.
+- Sort UserOps by aggregator, to create the lists of UserOps-per-aggregator.
+- For each aggregator, run the aggregator-specific code to create aggregated signature, and update the UserOps
+
+After creating the batch, before including the transaction in a block, the client should:
+
+- Run `debug_traceCall` with maximum possible gas, to enforce the validation rules on opcode and storage access.
+ as well as to verify the entire `handleOps` batch transaction,
+ and use the consumed gas for the actual transaction execution.
+- If the call reverted, the bundler MUST use the trace result to find the entity that reverted the call. \
+ This is the last entity that is CALL'ed by the EntryPoint prior to the revert. \
+ (the bundler cannot assume the revert is `FailedOp`)
+- If any verification context rule was violated the bundlers should treat it the same as
+ if this UserOperation reverted.
+- Remove the offending UserOperation from the current bundle and from mempool.
+- If the error is caused by a `factory` or a `paymaster`, and the `sender`
+ of the UserOp **is not** a staked entity, then issue a "ban" (see ["Reputation, throttling and banning"](#reputation-scoring-and-throttlingbanning-for-global-entities))
+ for the guilty factory or paymaster.
+- If the error is caused by a `factory` or a `paymaster`, and the `sender`
+ of the UserOp **is** a staked entity, do not ban the `factory` / `paymaster` from the mempool.
+ Instead, issue a "ban" for the staked `sender` entity.
+- Repeat until `debug_traceCall` succeeds.
+
+As staked entries may use some kind of transient storage to communicate data between UserOperations in the same bundle,
+it is critical that the exact same opcode and precompile banning rules as well as storage access rules are enforced
+for the `handleOps` validation in its entirety as for individual UserOperations.
+Otherwise, attackers may be able to use the banned opcodes to detect running on-chain and trigger a `FailedOp` revert.
+
+When a bundler includes a bundle in a block it must ensure that earlier transactions in the block don't make any UserOperation fail. It should either use access lists to prevent conflicts, or place the bundle as the first transaction in the block.
+
+### Error codes.
+
+While performing validation, the EntryPoint must revert on failures. During simulation, the calling bundler MUST be able to determine which entity (factory, account or paymaster) caused the failure.
+The attribution of revert to entity is done using the call-tracing: the last entity called by the EntryPoint prior the revert is the entity that caused the revert.
+
+- For diagnostic purposes, the EntryPoint must only revert with explicit FailedOp() or FailedOpWithRevert() errors.
+- The message of the error starts with event code, AA##
+- Event code starting with "AA1" signify an error during account creation
+- Event code starting with "AA2" signify an error during account validation (validateUserOp)
+- Event code starting with "AA3" signify an error during paymaster validation (validatePaymasterUserOp)
+
+## Rationale
+
+The main challenge with a purely smart contract wallet based account abstraction system is DoS safety: how can a block builder including an operation make sure that it will actually pay fees, without having to first execute the entire operation? Requiring the block builder to execute the entire operation opens a DoS attack vector, as an attacker could easily send many operations that pretend to pay a fee but then revert at the last moment after a long execution. Similarly, to prevent attackers from cheaply clogging the mempool, nodes in the P2P network need to check if an operation will pay a fee before they are willing to forward it.
+
+The first step is clean separation between validation (acceptance of UserOperation, and acceptance to pay) and execution.
+In this proposal, we expect accounts to have a `validateUserOp` method that takes as input a `UserOperation`, and verify the signature and pay the fee.
+Only if this method returns successfully, the execution will happen.
+
+The entry point-based approach allows for a clean separation between verification and execution, and keeps accounts' logic simple. It enforces the simple rule that only after validation is successful (and the UserOp can pay), the execution is done, and also guarantees the fee payment.
+
+The last step is protecting the bundlers from denial-of-service attacks by a mass number of UserOperation that appear to be valid (and pay) but that eventually revert, and thus block the bundler from processing valid UserOperations.
+For this purpose, the bundler requires a set of [restrictions on the validation function](./erc-7526.md), to prevent such denial-of-service attacks.
+
+### Reputation scoring and throttling/banning for global entities
+
+#### Reputation Rationale.
+
+UserOperation's storage access rules prevent them from interfere with each other.
+But "global" entities - paymasters, factories and aggregators are accessed by multiple UserOperations, and thus might invalidate multiple previously-valid UserOperations.
+
+To prevent abuse, we throttle down (or completely ban for a period of time) an entity that causes invalidation of large number of UserOperations in the mempool.
+To prevent such entities from "sybil-attack", we require them to stake with the system, and thus make such DoS attack very expensive.
+Note that this stake is never slashed, and can be withdrawn any time (after unstake delay)
+
+Unstaked entities are allowed, under the rules below.
+
+When staked, an entity is less restricted in its memory usage.
+
+The stake value is not enforced on-chain, but specifically by each node while simulating a transaction.
+
+### Paymasters
+
+Paymaster contracts allow abstraction of gas: having a contract, that is not the sender of the transaction, pay for the transaction fees.
+
+Paymaster architecture allows them to follow the model of "pre-charge, and later refund".
+E.g. a token-paymaster may pre-charge the user with the max possible price of the transaction, and refund the user with the excess afterwards.
+
+### First-time account creation
+
+It is an important design goal of this proposal to replicate the key property of EOAs that users do not need to perform some custom action or rely on an existing user to create their wallet; they can simply generate an address locally and immediately start accepting funds.
+
+The wallet creation itself is done by a "factory" contract, with wallet-specific data.
+The factory is expected to use CREATE2 (not CREATE) to create the wallet, so that the order of creation of wallets doesn't interfere with the generated addresses.
+The `initCode` field (if non-zero length) is parsed as a 20-byte address, followed by "calldata" to pass to this address.
+This method call is expected to create a wallet and return its address.
+If the factory does use CREATE2 or some other deterministic method to create the wallet, it's expected to return the wallet address even if the wallet has already been created. This is to make it easier for clients to query the address without knowing if the wallet has already been deployed, by simulating a call to `entryPoint.getSenderAddress()`, which calls the factory under the hood.
+When `initCode` is specified, if either the `sender` address points to an existing contract, or (after calling the initCode) the `sender` address still does not exist,
+then the operation is aborted.
+The `initCode` MUST NOT be called directly from the entryPoint, but from another address.
+The contract created by this factory method should accept a call to `validateUserOp` to validate the UserOp's signature.
+For security reasons, it is important that the generated contract address will depend on the initial signature.
+This way, even if someone can create a wallet at that address, he can't set different credentials to control it.
+The factory has to be staked if it accesses global storage - see [reputation, throttling and banning section](#reputation-scoring-and-throttlingbanning-for-global-entities) for details.
+
+NOTE: In order for the wallet to determine the "counterfactual" address of the wallet (prior its creation),
+it should make a static call to the `entryPoint.getSenderAddress()`
+
+### Entry point upgrading
+
+Accounts are encouraged to be DELEGATECALL forwarding contracts for gas efficiency and to allow account upgradability. The account code is expected to hard-code the entry point into their code for gas efficiency. If a new entry point is introduced, whether to add new functionality, improve gas efficiency, or fix a critical security bug, users can self-call to replace their account's code address with a new code address containing code that points to a new entry point. During an upgrade process, it's expected that two mempools will run in parallel.
+
+### RPC methods (eth namespace)
+
+#### \* eth_sendUserOperation
+
+eth_sendUserOperation submits a User Operation object to the User Operation pool of the client. The client MUST validate the UserOperation, and return a result accordingly.
+
+The result `SHOULD` be set to the **userOpHash** if and only if the request passed simulation and was accepted in the client's User Operation pool. If the validation, simulation, or User Operation pool inclusion fails, `result` `SHOULD NOT` be returned. Rather, the client `SHOULD` return the failure reason.
+
+##### Parameters:
+
+1. **UserOperation** a full user-operation struct. All fields MUST be set as hex values. empty `bytes` block (e.g. empty `initCode`) MUST be set to `"0x"`
+2. **factory** and **factoryData** - either both exist, or none
+3. paymaster fields (**paymaster**, **paymasterData**, **paymasterValidationGasLimit**, **paymasterPostOpGasLimit**) either all exist, or none.
+4. **EntryPoint** the entrypoint address the request should be sent through. this MUST be one of the entry points returned by the `supportedEntryPoints` rpc call.
+
+##### Return value:
+
+- If the UserOperation is valid, the client MUST return the calculated **userOpHash** for it
+- in case of failure, MUST return an `error` result object, with `code` and `message`. The error code and message SHOULD be set as follows:
+ - **code: -32602** - invalid UserOperation struct/fields
+ - **code: -32500** - transaction rejected by entryPoint's simulateValidation, during wallet creation or validation
+ - The `message` field MUST be set to the FailedOp's "`AAxx`" error message from the EntryPoint
+ - **code: -32501** - transaction rejected by paymaster's validatePaymasterUserOp
+ - The `message` field SHOULD be set to the revert message from the paymaster
+ - The `data` field MUST contain a `paymaster` value
+ - **code: -32502** - transaction rejected because of opcode validation
+ - **code: -32503** - UserOperation out of time-range: either wallet or paymaster returned a time-range, and it is already expired (or will expire soon)
+ - The `data` field SHOULD contain the `validUntil` and `validAfter` values
+ - The `data` field SHOULD contain a `paymaster` value, if this error was triggered by the paymaster
+ - **code: -32504** - transaction rejected because paymaster (or signature aggregator) is throttled/banned
+ - The `data` field SHOULD contain a `paymaster` or `aggregator` value, depending on the failed entity
+ - **code: -32505** - transaction rejected because paymaster (or signature aggregator) stake or unstake-delay is too low
+ - The `data` field SHOULD contain a `paymaster` or `aggregator` value, depending on the failed entity
+ - The `data` field SHOULD contain a `minimumStake` and `minimumUnstakeDelay`
+ - **code: -32506** - transaction rejected because wallet specified unsupported signature aggregator
+ - The `data` field SHOULD contain an `aggregator` value
+ - **code: -32507** - transaction rejected because of wallet signature check failed (or paymaster signature, if the paymaster uses its data as signature)
+
+##### Example:
+
+Request:
+
+```json=
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "eth_sendUserOperation",
+ "params": [
+ {
+ sender, // address
+ nonce, // uint256
+ factory, // address
+ factoryData, // bytes
+ callData, // bytes
+ callGasLimit, // uint256
+ verificationGasLimit, // uint256
+ preVerificationGas, // uint256
+ maxFeePerGas, // uint256
+ maxPriorityFeePerGas, // uint256
+ paymaster, // address
+ paymasterVerificationGasLimit, // uint256
+ paymasterPostOpGasLimit, // uint256
+ paymasterData, // bytes
+ signature // bytes
+ },
+ entryPoint // address
+ ]
+}
+
+```
+
+Response:
+
+```
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x1234...5678"
+}
+```
+
+##### Example failure responses:
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "error": {
+ "message": "AA21 didn't pay prefund",
+ "code": -32500
+ }
+}
+```
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "error": {
+ "message": "paymaster stake too low",
+ "data": {
+ "paymaster": "0x123456789012345678901234567890123456790",
+ "minimumStake": "0xde0b6b3a7640000",
+ "minimumUnstakeDelay": "0x15180"
+ },
+ "code": -32504
+ }
+}
+```
+
+#### \* eth_estimateUserOperationGas
+
+Estimate the gas values for a UserOperation.
+Given UserOperation optionally without gas limits and gas prices, return the needed gas limits.
+The signature field is ignored by the wallet, so that the operation will not require user's approval.
+Still, it might require putting a "semi-valid" signature (e.g. a signature in the right length)
+
+**Parameters**:
+
+- Same as `eth_sendUserOperation`\
+ gas limits (and prices) parameters are optional, but are used if specified.
+ `maxFeePerGas` and `maxPriorityFeePerGas` default to zero, so no payment is required by neither account nor paymaster.
+- Optionally accepts the `State Override Set` to allow users to modify the state during the gas estimation.\
+ This field as well as its behavior is equivalent to the ones defined for `eth_call` RPC method.
+
+**Return Values:**
+
+- **preVerificationGas** gas overhead of this UserOperation
+- **verificationGasLimit** actual gas used by the validation of this UserOperation
+- **callGasLimit** value used by inner account execution
+- **paymasterVerificationGasLimit** value used for paymaster verification (if paymaster exists in the UserOperation)
+- **paymasterPostOpGasLimit** value used for paymaster post op execution (if paymaster exists in the UserOperation)
+
+##### Error Codes:
+
+Same as `eth_sendUserOperation`
+This operation may also return an error if the inner call to the account contract reverts.
+
+#### \* eth_getUserOperationByHash
+
+Return a UserOperation based on a hash (userOpHash) returned by `eth_sendUserOperation`
+
+**Parameters**
+
+- **hash** a userOpHash value returned by `eth_sendUserOperation`
+
+**Return value**:
+
+- If the UserOperation is included in a block:
+ - Return a full UserOperation, with the addition of `entryPoint`, `blockNumber`, `blockHash` and `transactionHash`.
+
+- Else if the UserOperation is pending in the bundler's mempool:
+ - MAY return `null`, or: a full UserOperation, with the addition of the `entryPoint` field and a `null` value for `blockNumber`, `blockHash` and `transactionHash`.
+
+- Else:
+ - Return `null`
+
+#### \* eth_getUserOperationReceipt
+
+Return a UserOperation receipt based on a hash (userOpHash) returned by `eth_sendUserOperation`
+
+**Parameters**
+
+- **hash** a userOpHash value returned by `eth_sendUserOperation`
+
+**Return value**:
+
+`null` in case the UserOperation is not yet included in a block, or:
+
+- **userOpHash** the request hash
+- **entryPoint**
+- **sender**
+- **nonce**
+- **paymaster** the paymaster used for this userOp (or empty)
+- **actualGasCost** - actual amount paid (by account or paymaster) for this UserOperation
+- **actualGasUsed** - total gas used by this UserOperation (including preVerification, creation, validation and execution)
+- **success** boolean - did this execution completed without revert
+- **reason** in case of revert, this is the revert reason
+- **logs** the logs generated by this UserOperation (not including logs of other UserOperations in the same bundle)
+- **receipt** the TransactionReceipt object.
+ Note that the returned TransactionReceipt is for the entire bundle, not only for this UserOperation.
+
+#### \* eth_supportedEntryPoints
+
+Returns an array of the entryPoint addresses supported by the client. The first element of the array `SHOULD` be the entryPoint addressed preferred by the client.
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "eth_supportedEntryPoints",
+ "params": []
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": [
+ "0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8",
+ "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6"
+ ]
+}
+```
+
+#### \* eth_chainId
+
+Returns [EIP-155](./eip-155.md) Chain ID.
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "eth_chainId",
+ "params": []
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0x1"
+}
+```
+
+### RPC methods (debug Namespace)
+
+This api must only be available on testing mode and is required by the compatibility test suite. In production, any `debug_*` rpc calls should be blocked.
+
+#### \* debug_bundler_clearState
+
+Clears the bundler mempool and reputation data of paymasters/accounts/factories/aggregators.
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_clearState",
+ "params": []
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "ok"
+}
+```
+
+#### \* debug_bundler_dumpMempool
+
+Dumps the current UserOperations mempool
+
+**Parameters:**
+
+- **EntryPoint** the entrypoint used by eth_sendUserOperation
+
+**Returns:**
+
+`array` - Array of UserOperations currently in the mempool.
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_dumpMempool",
+ "params": ["0x1306b01bC3e4AD202612D3843387e94737673F53"]
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": [
+ {
+ sender, // address
+ nonce, // uint256
+ factory, // address
+ factoryData, // bytes
+ callData, // bytes
+ callGasLimit, // uint256
+ verificationGasLimit, // uint256
+ preVerificationGas, // uint256
+ maxFeePerGas, // uint256
+ maxPriorityFeePerGas, // uint256
+ signature // bytes
+ }
+ ]
+}
+```
+
+#### \* debug_bundler_sendBundleNow
+
+Forces the bundler to build and execute a bundle from the mempool as `handleOps()` transaction.
+
+Returns: `transactionHash`
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_sendBundleNow",
+ "params": []
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "0xdead9e43632ac70c46b4003434058b18db0ad809617bd29f3448d46ca9085576"
+}
+```
+
+#### \* debug_bundler_setBundlingMode
+
+Sets bundling mode.
+
+After setting mode to "manual", an explicit call to debug_bundler_sendBundleNow is required to send a bundle.
+
+##### parameters:
+
+`mode` - 'manual' | 'auto'
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_setBundlingMode",
+ "params": ["manual"]
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "ok"
+}
+```
+
+#### \* debug_bundler_setReputation
+
+Sets reputation of given addresses. parameters:
+
+**Parameters:**
+
+- An array of reputation entries to add/replace, with the fields:
+ - `address` - The address to set the reputation for.
+ - `opsSeen` - number of times a user operations with that entity was seen and added to the mempool
+ - `opsIncluded` - number of times a user operations that uses this entity was included on-chain
+
+- **EntryPoint** the entrypoint used by eth_sendUserOperation
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_setReputation",
+ "params": [
+ [
+ {
+ "address": "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6",
+ "opsSeen": "0x14",
+ "opsIncluded": "0x0D"
+ }
+ ],
+ "0x1306b01bC3e4AD202612D3843387e94737673F53"
+ ]
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "ok"
+}
+```
+
+#### \* debug_bundler_dumpReputation
+
+Returns the reputation data of all observed addresses.
+Returns an array of reputation objects, each with the fields described above in `debug_bundler_setReputation` with the
+
+**Parameters:**
+
+- **EntryPoint** the entrypoint used by eth_sendUserOperation
+
+**Return value:**
+
+An array of reputation entries with the fields:
+
+- `address` - The address to set the reputation for.
+- `opsSeen` - number of times a user operations with that entity was seen and added to the mempool
+- `opsIncluded` - number of times a user operations that uses this entity was included on-chain
+- `status` - (string) The status of the address in the bundler 'ok' | 'throttled' | 'banned'.
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_dumpReputation",
+ "params": ["0x1306b01bC3e4AD202612D3843387e94737673F53"]
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": [
+ { "address": "0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6",
+ "opsSeen": "0x14",
+ "opsIncluded": "0x13",
+ "status": "ok"
+ }
+ ]
+}
+```
+
+#### \* debug_bundler_addUserOps
+
+Accept UserOperations into the mempool.
+Assume the given UserOperations all pass validation (without actually validating them), and accept them directly into th mempool
+
+**Parameters:**
+
+- An array of UserOperations
+
+```json=
+# Request
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "debug_bundler_addUserOps",
+ "params": [
+ [
+ { sender: "0xa...", ... },
+ { sender: "0xb...", ... }
+ ]
+ ]
+}
+
+# Response
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": "ok"
+}
+```
+
+## Backwards Compatibility
+
+This ERC does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. Unfortunately it is not easily compatible with pre-[ERC-4337](./eip-4337.md) accounts, because those accounts do not have a `validateUserOp` function. If the account has a function for authorizing a trusted op submitter, then this could be fixed by creating an [ERC-4337](./eip-4337.md) compatible account that re-implements the verification logic as a wrapper and setting it to be the original account's trusted op submitter.
+
+## Reference Implementation
+
+See `https://github.com/eth-infinitism/account-abstraction/tree/main/contracts`
+
+## Security Considerations
+
+The entry point contract will need to be very heavily audited and formally verified, because it will serve as a central trust point for _all_ [ERC-4337]. In total, this architecture reduces auditing and formal verification load for the ecosystem, because the amount of work that individual _accounts_ have to do becomes much smaller (they need only verify the `validateUserOp` function and its "check signature and pay fees" logic) and check that other functions are `msg.sender == ENTRY_POINT` gated (perhaps also allowing `msg.sender == self`), but it is nevertheless the case that this is done precisely by concentrating security risk in the entry point contract that needs to be verified to be very robust.
+
+Verification would need to cover two primary claims (not including claims needed to protect paymasters, and claims needed to establish p2p-level DoS resistance):
+
+- **Safety against arbitrary hijacking**: The entry point only calls an account generically if `validateUserOp` to that specific account has passed (and with `op.calldata` equal to the generic call's calldata)
+- **Safety against fee draining**: If the entry point calls `validateUserOp` and passes, it also must make the generic call with calldata equal to `op.calldata`
+
+## Copyright
+
+Copyright and related rights waived via [CC0](../LICENSE.md).
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/ERCS/erc-7562.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/ERCS/erc-7562.md
new file mode 100644
index 000000000..6126265cf
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/ERCS/erc-7562.md
@@ -0,0 +1,393 @@
+---
+eip: 7562
+title: Account Abstraction Validation Scope Rules
+description: A set of limitations on validation EVM code to protect Account Abstraction nodes from denial-of-service attacks through unpaid computation.
+author: Yoav Weiss (@yoavw), Dror Tirosh (@drortirosh), Alex Forshtat (@forshtat), Shahaf Nacson (@shahafn)
+discussions-to: https://ethereum-magicians.org/t/erc-7562-account-abstraction-validation-scope-rules/16683
+status: Draft
+type: Standards Track
+category: ERC
+created: 2023-09-01
+---
+
+## Abstract
+
+This document describes the rules we impose on the validation context of Account Abstraction transactions,
+such as [ERC-4337](./erc-4337.md) `UserOperation` or [RIP-7560](./rip-7560.md) (Native Account Abstraction), which are enforced off-chain by a
+block builder or a standalone bundler, and the rationale behind each one of them.
+
+## Motivation
+
+With Account-Abstraction, instead of hard-coded logic for processing a transaction (validation, gas-payment, and execution), this logic is executed by EVM code.
+The benefits for the account are countless -
+
+- abstracting the validation allows the contract to use different signature schemes, multisig configuration, custom recovery, and more.
+- abstracting gas payments allows easy onboarding by 3rd party payments, paying with tokens, cross-chain gas payments
+- abstracting execution allows batch transactions
+
+All of the above are missing from the EOA account model.
+
+However, there is one rule a transaction must follow to preserve the decentralized network: once submitted into the network (the mempool), the transaction is guaranteed to pay. This comes to prevent denial of service attacks on the network.
+
+The EOA model implicitly follows the rule: a valid transaction can't become invalid without payment by the account: e.g account balance can't be reduced (except with a higher paying transaction)
+
+This simple rule makes the network sustainable and DoS-protected: the network can't be cheaply attacked by a mass of transactions. An attack (sending a mass of transactions) is expensive, and gets more expensive as the network clogs. Legitimate users pay more, and can delay operations to avoid the cost, but the attacker pays a huge (and increasing) amount to keep the network clogged.
+
+For Account-Abstraction system we want to keep the same rule, so that attempting a DoS attack on the network should be as expensive.
+In order to do so, we add the following validation rules.
+
+For the actual interfaces of those contract-based accounts see the definitions in ERC-4337 and RIP-7560.
+
+This documentation uses the terminology "UserOperation" for a transaction created by a smart contract account, and closely follows [ERC-4337](./erc-4337.md) terminology.
+However, the rules apply to any account-abstraction framework that uses EVM code to perform transaction validation and makes a distinction between validation and execution.
+
+## Rationale
+
+All transactions initiated by EOAs have an implicit validation phase where balance, nonce, and signature are
+checked to be valid for the current state of the Ethereum blockchain.
+Once the transaction is checked to be valid by a node, only another transaction by the same EOA can modify the Ethereum
+state in a way that makes the first transaction invalid.
+
+With Account Abstraction, however, the validation can also include an arbitrary EVM code and rely on storage as well,
+which means that unrelated `UserOperations` or transactions may invalidate each other.
+
+If not addressed, this would make the job of maintaining a mempool of valid `UserOperations` and producing valid
+bundles computationally infeasible and susceptible to DoS attacks.
+
+This document describes a set of validation rules that if applied by a bundler before accepting a `UserOperation`
+into the mempool can prevent such attacks.
+
+### The high-level goal
+
+The purpose of this specification is to define a consensus between nodes (bundlers or block-builders) when processing incoming UserOperations from an external source.
+This external source for UserOperations is either an end-user node (via RPC) or another node in the p2p network.
+
+The protocol tries to detect "spam" - which are large bursts of UserOperations that cannot be included on-chain (and thus can't pay).
+The network is protected by throttling down requests from such spammer nodes.
+
+All nodes in the network must have the same definition of "spam": otherwise, if some nodes accept some type of UserOperations and propagate them while others consider them spam, those "forgiving" nodes will be considered "spammers" by the rest of the nodes, and the network effectively gets split.
+
+### The processing flow of a UserOperation
+
+- First, a UserOperation is received - either via RPC (submitted on behalf of a single application) or via the p2p protocol, from another node in the mempool.
+- The node performs validation on the UserOperation, and then adds it to its in-memory mempool, and submits it to its peers.
+- Lastly, when building a block, a node collects UserOperations from the mempool, performs a 2nd validation to make sure they are all still valid as a bundle and submits them into the next block.
+
+### The need for 2nd validation before submitting a block
+
+A normal Ethereum transaction in the mempool can be invalidated if another transaction was received with the same nonce. That other transaction had to increase the gas price in order to replace the first one, so it satisfied the rule of "must pay to get included into the mempool"
+With contract-based accounts, since the UserOperation validity may depend on mutable state, other transactions may invalidate a previously valid UserOperation, so we must check it before inclusion
+
+### Rationale of limiting opcodes:
+
+- the validation is performed off-chain, before creating a block. Some opcodes access information that is known only when creating the block.
+- using those opcodes while validating a transaction can easily create a validation rule that will succeed off-chain, but always revert on-chain, and thus cause a DoS attack.
+- a simple example is `require block.number==12345`. It can be valid when validating the UserOperation and adding it to the mempool
+ but will be invalid when attempting to include it on-chain at a later block.
+
+### Rationale for limiting storage access
+
+- We need UserOperation validations not to overlap so that a single storage change can't easily invalidate a large number of UserOperations in the mempool. By limiting UserOperations to access storage associated with the account itself, we know that we can for sure include a single UserOperation for each account in a bundle
+- (A bundler MAY include more than one UserOperation of an account in a bundle, MUST first validate them together)
+
+### Rationale of requiring a stake
+
+We want to be able to allow globally-used contracts (paymasters, factories) to use storage not associated with the account, but still prevent them from
+spamming the mempool.
+If a contract causes too many UserOperations to fail in their second validation after succeeding in their first, we can throttle its use in the mempool.
+By requiring such a contract to have a stake, we prevent a "Sybil attack", by making it expensive to create a large number of such paymasters to continue the spam attack.
+
+By following the validation rules, we can detect contracts that cause spam UserOperations, and throttle them.
+The stake comes to prevent the fast re-creation of malicious entities.
+The stake is never slashed (since it is only used for off-chain detection) but is locked for a period of time, which makes such an attack much more expensive.
+
+### Definition of the `mass invalidation attack`
+
+A possible set of actions is considered to be a `mass invalidation attack` on the network if a large number of
+`UserOperations` that did pass the initial validation and were accepted by nodes and propagated further into the
+mempool to other bundlers in the network becomes invalid and not eligible for inclusion in a block.
+
+There are 3 ways to perform such an attack:
+
+1. Submit `UserOperation`s that pass the initial validation, but later fail the re-validation
+ that is performed during the bundle creation.
+2. Submit `UserOperation`s that are valid in isolation during validation, but when bundled
+ together become invalid.
+3. Submit valid `UserOperation`s but "front-run" them by executing a state change on the
+ network that causes them to become invalid. The "front-run" in question must be economically viable.
+
+To prevent such attacks, we attempt to "sandbox" the validation code.
+We isolate the validation code from other `UserOperations`, from external changes to the storage, and
+from information about the environment such as a current block timestamp.
+
+### What is not considered a `mass invalidation attack`
+
+A `UserOperation` that fails the initial validation by a receiving node without entering its mempool is not
+considered an attack. The node is expected to apply web2 security measures and throttle requests based on API key,
+source IP address, etc.
+RPC nodes already do that to prevent being spammed with invalid transactions which also have a validation cost.
+P2P nodes already have (and should apply) a scoring mechanism to determine spammer nodes.
+
+Also, if the invalidation of `N` UserOperations from the mempool costs `N*X` with a sufficiently large `X`, it is not considered an economically viable attack.
+
+- The minimum change to cause an invalidation is a storage change (5k gas)
+- Assuming a Node can sustain processing 2000 invalid UserOps per block, the cost of a DoS attack is 10M gas per block.
+- The above value is high, but we take further measures to make such an attack more expensive.
+
+## Specification
+
+### Rule Types
+
+There are two types of rules:
+
+- **Network-wide rules** rules that MUST be applied to each UserOperation before accepting it into the local mempool and propagating it.
+ These rules include the opcode and storage rules.
+ - Failing these validation rules SHOULD drop the UserOperation
+ - Failing these validations during 2nd validation phase (before submitting a bundle) SHOULD degrade
+ the reputation of the offending entity
+ - Bundler MUST NOT propagate UserOperations that fail the validation rules, otherwise
+ it will be considered a "spammer" by other bundlers in the mempool, and get disconnected.
+
+- **Local rules**
+ These are "soft" rules, based on the reputation of entities.
+ These rules come to protect the bundler itself from spamming attacks.
+ - Bundlers SHOULD drop such UserOperations without performing validation.
+ - Bundlers SHOULD NOT propagate such UserOperations to other bundlers.
+ - Bundlers SHOULD NOT consider another bundler a "spammer" if it does.
+
+### Constants
+
+| Title | Value | Comment |
+| ------------------------------------ | --------------------------- | ------------------------------------------------------------------------------- |
+| `MIN_UNSTAKE_DELAY` | 86400 | 1 day |
+| `MIN_STAKE_VALUE` | Adjustable per chain value | Equivalent to ~$1000 in native tokens |
+| `SAME_SENDER_MEMPOOL_COUNT` | 4 | |
+| `SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT` | 10 | |
+| `THROTTLED_ENTITY_MEMPOOL_COUNT` | 4 | Number of `UserOperations` with a throttled entity that can stay in the mempool |
+| `THROTTLED_ENTITY_LIVE_BLOCKS` | 10 | Number of blocks a `UserOperations` with a throttled entity can stay in mempool |
+| `THROTTLED_ENTITY_BUNDLE_COUNT` | 4 | |
+| `MIN_INCLUSION_RATE_DENOMINATOR` | 100 (client) \ 10 (bundler) | |
+| `THROTTLING_SLACK` | 10 | |
+| `BAN_SLACK` | 50 | |
+| `BAN_OPS_SEEN_PENALTY` | 10000 | |
+| `MAX_OPS_ALLOWED_UNSTAKED_ENTITY` | 10000 |
+
+### Validation Rules
+
+### **Definitions**:
+
+1. **Validation Phases**: there are up to 3 phases of validation
+ 1. smart account deployment
+ 2. smart account validation
+ 3. paymaster validation.
+2. **Entity**: a contract that is explicitly specified by the `UserOperation`.
+ Includes the `factory`, `paymaster`, `aggregator`, and staked `account`, as discussed below. \
+ Each "validation phase" is attributed to a single entity. \
+ Entity contracts must have non-empty code on-chain.
+3. **Canonical Mempool**: The rules defined in this document apply to the main mempool shared by all bundlers on the network.
+4. **Staked Entity:** an entity that has a locked stake of at least `MIN_STAKE_VALUE`
+ and an unstake delay of at least `MIN_UNSTAKE_DELAY`.
+5. **Associated storage:** a storage slot of any smart contract is considered to be "associated" with address `A` if:
+ 1. The slot value is `A`
+ 2. The slot value was calculated as `keccak(A||x)+n`, where `x` is a `bytes32` value, and `n` is a value in the range 0..128
+6. **Using an address**: accessing the code of a given address in any way.
+ This can be done by executing `*CALL` or `EXTCODE*` opcodes for a given address.
+
+### Reputation Definitions
+
+1. **opsSeen**: a per-entity counter of how many times a unique valid `UserOperation` referencing this entity
+ was received by this bundler.
+ This includes `UserOperation` received via incoming RPC calls or through a P2P mempool protocol.
+
+2. **opsIncluded**: a per-entity counter of how many times a unique valid `UserOperation` referencing this entity
+ appeared in an actual included `UserOperation`. \
+ Calculation of this value is based on UserOperationEvents and is only counted for `UserOperations` that were
+ previously counted as `opsSeen` by this bundler.
+3. Both values are updated every hour as `value = value * 23 // 24` \
+ Effectively, the value is reduced to 1% after 4 days.
+4. **inclusionRate**: Relation of `opsIncluded` to `opsSeen`
+
+### Reputation Calculation
+
+We define a value `max_seen = opsSeen // MIN_INCLUSION_RATE_DENOMINATOR`.
+
+The reputation state of each entity is determined as follows:
+
+1. **BANNED**: `max_seen > opsIncluded + BAN_SLACK`
+2. **THROTTLED**: `max_seen > opsIncluded + THROTTLING_SLACK`
+3. **OK**: otherwise
+
+Note that new entities start with an `OK` reputation.
+
+To help make sense of these params, note that a malicious paymaster can at most cause the network (only the p2p network, not the blockchain) to process `BAN_SLACK * MIN_INCLUSION_RATE_DENOMINATOR / 24` non-paying ops per hour.
+
+### Running the Validation Rules
+
+1. A block builder or a bundler should perform a full validation before accepting a `UserOperation` into its mempool.
+2. During the validation phase, the bundler should trace the execution and apply all the rules defined in this document.
+3. A bundler should also perform a full validation of the entire bundle before submission.
+4. The validation rules prevent an unstaked entity from detecting the bundle validation.
+ However, a malicious staked entity can detect that it is running in a bundle validation and cause a revert.
+5. The failed `UserOperation` should be dropped from the bundle.
+6. The staked entity that caused a revert violated the Account Abstraction rules and should be marked as `THROTTLED`.
+
+### Mempool Validation Rules
+
+1. A `UserOperation` is broadcast over the P2P protocol with the following information:
+ 1. The `UserOperation` itself
+ 2. The blockhash this `UserOperation` was originally verified against.
+2. Once a `UserOperation` is received from another bundler it should be verified locally by a receiving bundler.
+3. A received `UserOperation` may fail any of the reasonable static checks, such as: \
+ invalid format, values below minimum, submitted with a blockhash that isn't recent, etc. \
+ In this case, the bundler should drop this particular `UserOperation` but keep the connection.
+4. The bundler should check the `UserOperation` against the nonces of last-included bundles. \
+ Silently drop `UserOperations` with `nonce` that was recently included.
+ This invalidation is likely attributable to a network race condition and should not cause a reputation change.
+5. If a received `UserOperation` fails against the current block:
+ 1. Retry the validation against the block the `UserOperation` was originally verified against.
+ 2. If it succeeds, silently drop the `UserOperation` and keep the connection.
+ 3. If it fails, mark the sender as a "spammer"
+
+### Opcode Rules
+
+- Block access from opcodes that access information outside of storage and code (aka "environment").
+ - **[OP-011]** Blocked Opcodes:
+ - `BALANCE` (`0x31`)
+ - `ORIGIN` (`0x32`)
+ - `GASPRICE` (`0x3A`)
+ - `BLOCKHASH` (`0x40`)
+ - `COINBASE` (`0x41`)
+ - `TIMESTAMP` (`0x42`)
+ - `NUMBER` (`0x43`)
+ - `PREVRANDAO`/`DIFFICULTY` (`0x44`)
+ - `GASLIMIT` (`0x45`)
+ - `SELFBALANCE` (`0x47`)
+ - `BASEFEE` (`0x48`)
+ - `GAS` (`0x5A`)
+ - `CREATE` (`0xF0`)
+ - `INVALID` (`0xFE`)
+ - `SELFDESTRUCT` (`0xFF`)
+ - **[OP-012]** `GAS `opcode is allowed, but only if followed immediately by `*CALL` instructions.\
+ This is a common way to pass all remaining gas to an external call, and it means that the actual value is
+ consumed from the stack immediately and cannot be accessed by any other opcode.
+ - **[OP-13]** any "unassigned" opcode.
+- **[OP-020]** Revert on "out of gas" is forbidden as it can "leak" the gas limit or the current call stack depth.
+- Contract creation:
+ - **[OP-031]** `CREATE2` is allowed exactly once in the deployment phase and must deploy code for the "sender" address.
+- Access to an address without a deployed code is forbidden:
+ - **[OP-041]** For `EXTCODE*` and `*CALL` opcodes.
+ - **[OP-042]** Exception: access to the "sender" address is allowed.
+ This is only possible in `factory` code during the deployment phase.
+- Allowed access to the `EntryPoint` address:
+ - **[OP-051]** May call `EXTCODESIZE ISZERO`\
+ This pattern is used to check destination has a code before the `depositTo` function is called.
+ - **[OP-052]** May call `depositTo(sender)` with any value from either the `sender` or `factory`.
+ - **[OP-053]** May call the fallback function from the `sender` with any value.
+ - **[OP-054]** Any other access to the `EntryPoint` is forbidden.
+- `*CALL` opcodes:
+ - **[OP-061]** `CALL` with `value` is forbidden. The only exception is a call to the `EntryPoint` described above.
+ - **[OP-062]** Precompiles:
+ - Only allow known accepted precompiles on the network, that do not access anything in the blockchain state or environment.
+ - The core precompiles 0x1 .. 0x9
+ - The [RIP-7212](./rip-7212.md) sec256r1 precompile, on networks that accepted it.
+- **[OP-070]** Transient Storage slots defined in [EIP-1153](./eip-1153) and accessed using `TLOAD` (`0x5c`) and `TSTORE` (`0x5d`) opcodes
+ are treated exactly like persistent storage (SLOAD/SSTORE).
+
+### Code Rules
+
+- **[COD-010]** Between the first and the second validations, the `EXTCODEHASH` value of any visited address,
+ entity, or referenced library, may not be changed.\
+ If the code is modified, the UserOperation is considered invalid.
+
+### Storage Rules
+
+The permanent storage access with `SLOAD` and `SSTORE` instructions within each phase is limited as follows:
+
+- **[STO-010]** Access to the "account" storage is always allowed.
+- Access to associated storage of the account in an external (non-entity) contract is allowed if either:
+ - **[STO-021]** The account already exists.
+ - **[STO-022]** There is an `initCode` and the `factory` contract is staked.
+- If the entity (`paymaster`, `factory`) is staked, then it is also allowed:
+ - **[STO-031]** Access the entity's own storage.
+ - **[STO-032]** Read/Write Access to storage slots that are associated with the entity, in any non-entity contract.
+ - **[STO-033]** Read-only access to any storage in non-entity contract.
+
+### Local Rules
+
+Local storage rules protect the bundler against denial of service at the time of bundling. They do not affect mempool propagation and cannot cause a bundler to be marked as a "spammer".
+
+- **[STO-040]** `UserOperation` may not use an entity address (`factory`/`paymaster`/`aggregator`) that is used as an "account" in another `UserOperation` in the mempool. \
+ This means that `Paymaster` and `Factory` contracts cannot practically be an "account" contract as well.
+- **[STO-041]** `UserOperation` may not use associated storage (of either its account or from staked entity) in a contract that is a "sender" of another UserOperation in the mempool.
+
+### General Reputation Rules
+
+The following reputation rules apply for all staked entities, and for unstaked paymasters. All rules apply to all of these entities unless specified otherwise.
+
+- **[GREP-010]** A `BANNED` address is not allowed into the mempool.\
+ Also, all existing `UserOperations` referencing this address are removed from the mempool.
+- **[GREP-020]** A `THROTTLED` address is limited to:
+ - `THROTTLED_ENTITY_MEMPOOL_COUNT` entries in the mempool.
+ - `THROTTLED_ENTITY_BUNDLE_COUNT` `UserOperations` in a bundle.
+ - Can remain in the mempool only for `THROTTLED_ENTITY_LIVE_BLOCKS`.
+- **[GREP-040]** If an entity fails the bundle creation after passing second validation, its `opsSeen` set to `BAN_OPS_SEEN_PENALTY`, and `opsIncluded` to zero, causing it to be `BANNED`.
+
+### Staked Entities Reputation Rules
+
+- **[SREP-010]** The "canonical mempool" defines a staked entity if it has `MIN_STAKE_VALUE` and unstake delay of `MIN_UNSTAKE_DELAY`
+- **[SREP-020]** An `OK` staked entity is unlimited by the reputation rule.
+ - Allowed in unlimited numbers in the mempool.
+ - Allowed in unlimited numbers in a bundle.
+
+### Entity-specific Rules
+
+- **[EREP-010]** For each `paymaster`, the mempool must maintain the total gas `UserOperations` using this `paymaster` may consume.
+ - Do not add a `UserOperation` to the mempool if the maximum total gas cost, including the new `UserOperation`, is above the deposit of the `paymaster` at the current gas price.
+- **[EREP-015]** A `paymaster` should not have its opsSeen incremented on failure of factory or account
+ - When running 2nd validation (before inclusion in a bundle), if a UserOperation fails because of factory or account error (either a FailOp revert or validation rule), then the paymaster's opsSeen valid is decremented by 1.
+- **[EREP-020]** A staked factory is "accountable" for account breaking the rules. \
+ That is, if the `validateUserOp()` is rejected for any reason in a `UserOperation` that has an `initCode`, it is treated as if the factory caused this failure, and thus this affects its reputation.
+- **[EREP-030]** A Staked Account is accountable for failures in other entities (`paymaster`, `aggregator`) even if they are staked.
+- **[EREP-040]** An `aggregator` must be staked, regardless of storage usage.
+
+### Unstaked Paymasters Reputation Rules
+
+- Definitions:
+ - **`opsSeen`, `opsIncluded`, and reputation calculation** are defined above.
+ - `UnstakedReputation` of an entity determines the maximum number of entries using this entity allowed in the mempool.
+ - `opsAllowed` is a reputation-based calculation for an unstaked entity, representing how many `UserOperations` it is allowed to have in the mempool.
+ - Rules:
+ - **[UREP-010]** An unstaked sender is only allowed to have `SAME_SENDER_MEMPOOL_COUNT` `UserOperation`s in the mempool. A staked sender is only limited by the SREP rules.
+ - **[UREP-020]** For an unstaked paymaster only that is not throttled/banned: \
+ `opsAllowed = SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT + inclusionRate * min(opsIncluded, MAX_OPS_ALLOWED_UNSTAKED_ENTITY)`.
+ - This is a default of `SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT` for new entity
+
+### Alt-mempools Rules
+
+Alternate mempool is an agreed-upon rule that the bundlers may opt into, in addition to the canonical mempool
+The alt-mempool "topic" is a unique identifier. By convention, this is the IPFS hash of the document describing (in clear test and YAML file) the specifics of this alt mempool
+
+- **[ALT-010]** The bundler listens to the alt-mempool "topic" over the P2P protocol
+- **[ALT-020]** The alt mempool rules MUST be checked only when a canonical rule is violated
+ - That is, if validation follows the canonical rules above, it is not considered part of an alt-mempool.
+- **[ALT-021]** Such a `UserOperation` (that violates the canonical rules) is checked against all the "alternate mempools", and is considered part of all those alt-mempools
+- **[ALT-030]** Bundlers SHOULD forward `UserOperations` to other bundlers only once, regardless of how many (shared) alt-mempools they have. \
+ The receiving bundler validates the `UserOperations`, and based on the above rules (and subscribed alt-mempools) decides which alt-mempools to propagate it to.
+- **[ALT-040]** opsInclude and opsSeen of entities are kept per alt-mempool. That is, an entity can be considered throttled (or banned) in one mempool, while still active on another.
+
+### Alt-mempool Reputation
+
+Alt-mempools are served by the same bundlers participating in the canonical mempool, but change the rules and may introduce denial-of-service attack vectors. To prevent them from taking the canonical mempool or other alt mempools down with them, a reputation is managed for each. An alt mempool that causes too many invalidations gets throttled. This limits the scope of the attack and lets the bundler continue doing its work for other mempools.
+
+- **[AREP-010]** each alt-mempool manages "opsSeen" and "opsIncluded", much like entities. The opsSeen is incremented after `UserOperation` initial validation, where it is considered part of this mempool.
+ The "opsIncluded" is incremented after this UserOperation is included on-chain (either by this bundler, or another)
+- **[AREP-020]** the alt-mempool becomes THROTTLED based on the [Reputation Calculation](#reputation-calculation)
+
+## Security Considerations
+
+This document describes the security considerations bundlers must take to protect themselves (and the entire mempool network)
+from denial-of-service attacks.
+
+## Copyright
+
+Copyright and related rights waived via [CC0](../LICENSE.md).
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/bundle-seq-pm.svg b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/bundle-seq-pm.svg
new file mode 100644
index 000000000..67befce8e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/bundle-seq-pm.svg
@@ -0,0 +1 @@
+EntryPoint Account Paymaster Account2 1 handleOps(userOps[]): Validation 2 validateUserOp 3 validatePaymasterUserOp 4 deduct paymaster deposit Execution 5 exec 6 postOp 7 refund paymaster 8 compensate(beneficiary)
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/bundle-seq.svg b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/bundle-seq.svg
new file mode 100644
index 000000000..a637d705e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/bundle-seq.svg
@@ -0,0 +1 @@
+EntryPoint Factory Account Account2 1 handleOps(userOps[]): Validations 2 create (initCode) 3 create 4 account 5 validateUserOp 6 deposit 7 deduct account deposit 8 validateUserOp 9 deposit 10 deduct account2 deposit Executions 11 exec 12 refund account1 13 exec 14 refund account2 15 compensate(beneficiary)
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/image1.png b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/image1.png
new file mode 100644
index 000000000..ced8ea57d
Binary files /dev/null and b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/image1.png differ
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/image2.png b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/image2.png
new file mode 100644
index 000000000..6d0c6f71a
Binary files /dev/null and b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/erc/assets/erc-4337/image2.png differ
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/0-init-gas-checker.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/0-init-gas-checker.ts
new file mode 100644
index 000000000..78d6b7fc7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/0-init-gas-checker.ts
@@ -0,0 +1,12 @@
+import { GasCheckCollector, GasChecker } from './GasChecker'
+
+describe('gas calculations', function () {
+ this.timeout(60000)
+ const g = new GasChecker()
+
+ it('warmup', async function () {
+ await GasCheckCollector.init()
+ // dummy run - first run is slower.
+ await g.runTest({ title: 'simple', count: 1, diffLastGas: false })
+ })
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/1-simple-wallet.gas.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/1-simple-wallet.gas.ts
new file mode 100644
index 000000000..0943d1f0d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/1-simple-wallet.gas.ts
@@ -0,0 +1,17 @@
+import { GasChecker } from './GasChecker'
+
+context('simple account', function () {
+ this.timeout(60000)
+ const g = new GasChecker()
+
+ it('simple 1', async function () {
+ await g.addTestRow({ title: 'simple', count: 1, diffLastGas: false })
+ await g.addTestRow({ title: 'simple - diff from previous', count: 2, diffLastGas: true })
+ })
+
+ it('simple 10', async function () {
+ if (g.skipLong()) this.skip()
+ await g.addTestRow({ title: 'simple', count: 10, diffLastGas: false })
+ await g.addTestRow({ title: 'simple - diff from previous', count: 11, diffLastGas: true })
+ })
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/2-paymaster.gas.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/2-paymaster.gas.ts
new file mode 100644
index 000000000..ec95f9ad0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/2-paymaster.gas.ts
@@ -0,0 +1,59 @@
+import { parseEther } from 'ethers/lib/utils'
+import { TestPaymasterAcceptAll__factory } from '../typechain'
+import { ethers } from 'hardhat'
+import { GasChecker } from './GasChecker'
+import { Create2Factory } from '../src/Create2Factory'
+import { hexValue } from '@ethersproject/bytes'
+
+const ethersSigner = ethers.provider.getSigner()
+
+context('Minimal Paymaster', function () {
+ this.timeout(60000)
+ const g = new GasChecker()
+
+ let paymasterAddress: string
+ before(async () => {
+ const paymasterInit = hexValue(
+ new TestPaymasterAcceptAll__factory(ethersSigner).getDeployTransaction(g.entryPoint().address)
+ .data!
+ )
+ paymasterAddress = await new Create2Factory(ethers.provider, ethersSigner).deploy(
+ paymasterInit,
+ 0
+ )
+ const paymaster = TestPaymasterAcceptAll__factory.connect(paymasterAddress, ethersSigner)
+ await paymaster.addStake(1, { value: 1 })
+ await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') })
+ })
+ it('simple paymaster', async function () {
+ await g.addTestRow({
+ title: 'simple paymaster',
+ count: 1,
+ paymaster: paymasterAddress,
+ diffLastGas: false,
+ })
+ await g.addTestRow({
+ title: 'simple paymaster with diff',
+ count: 2,
+ paymaster: paymasterAddress,
+ diffLastGas: true,
+ })
+ })
+
+ it('simple paymaster 10', async function () {
+ if (g.skipLong()) this.skip()
+
+ await g.addTestRow({
+ title: 'simple paymaster',
+ count: 10,
+ paymaster: paymasterAddress,
+ diffLastGas: false,
+ })
+ await g.addTestRow({
+ title: 'simple paymaster with diff',
+ count: 11,
+ paymaster: paymasterAddress,
+ diffLastGas: true,
+ })
+ })
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/3-huge-tx-gas.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/3-huge-tx-gas.ts
new file mode 100644
index 000000000..2983473c5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/3-huge-tx-gas.ts
@@ -0,0 +1,27 @@
+import { DefaultGasTestInfo, GasChecker } from './GasChecker'
+
+context('huge tx - 5k', function () {
+ this.timeout(60000)
+ const huge = DefaultGasTestInfo.destCallData!.padEnd(10240, 'f')
+ const g = new GasChecker()
+
+ it('big tx 5k', async () => {
+ await g.addTestRow({ title: 'big tx 5k', count: 1, destCallData: huge, diffLastGas: false })
+ await g.addTestRow({
+ title: 'big tx - diff from previous',
+ count: 2,
+ destCallData: huge,
+ diffLastGas: true,
+ })
+ })
+ it('big tx 10', async function () {
+ if (g.skipLong()) this.skip()
+ await g.addTestRow({ title: 'big tx 5k', count: 10, destCallData: huge, diffLastGas: false })
+ await g.addTestRow({
+ title: 'big tx - diff from previous',
+ count: 11,
+ destCallData: huge,
+ diffLastGas: true,
+ })
+ })
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/4-paymaster-postop.gas.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/4-paymaster-postop.gas.ts
new file mode 100644
index 000000000..d33e38506
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/4-paymaster-postop.gas.ts
@@ -0,0 +1,62 @@
+import { parseEther } from 'ethers/lib/utils'
+import { TestPaymasterWithPostOp__factory } from '../typechain'
+import { ethers } from 'hardhat'
+import { GasChecker } from './GasChecker'
+import { Create2Factory } from '../src/Create2Factory'
+import { hexValue } from '@ethersproject/bytes'
+
+const ethersSigner = ethers.provider.getSigner()
+
+context('Paymaster with PostOp', function () {
+ this.timeout(60000)
+ const g = new GasChecker()
+
+ let paymasterAddress: string
+
+ before(async () => {
+ const paymasterInit = hexValue(
+ new TestPaymasterWithPostOp__factory(ethersSigner).getDeployTransaction(
+ g.entryPoint().address
+ ).data!
+ )
+ paymasterAddress = await new Create2Factory(ethers.provider, ethersSigner).deploy(
+ paymasterInit,
+ 0
+ )
+ const paymaster = TestPaymasterWithPostOp__factory.connect(paymasterAddress, ethersSigner)
+ await paymaster.addStake(1, { value: 1 })
+ await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') })
+ })
+
+ it('paymaster with PostOp', async function () {
+ await g.addTestRow({
+ title: 'paymaster+postOp',
+ count: 1,
+ paymaster: paymasterAddress,
+ diffLastGas: false,
+ })
+ await g.addTestRow({
+ title: 'paymaster+postOp with diff',
+ count: 2,
+ paymaster: paymasterAddress,
+ diffLastGas: true,
+ })
+ })
+
+ it('paymaster with postOp 10', async function () {
+ if (g.skipLong()) this.skip()
+
+ await g.addTestRow({
+ title: 'paymaster+postOp',
+ count: 10,
+ paymaster: paymasterAddress,
+ diffLastGas: false,
+ })
+ await g.addTestRow({
+ title: 'paymaster+postOp with diff',
+ count: 11,
+ paymaster: paymasterAddress,
+ diffLastGas: true,
+ })
+ })
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/5-token-paymaster.gas.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/5-token-paymaster.gas.ts
new file mode 100644
index 000000000..985d1ac97
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/5-token-paymaster.gas.ts
@@ -0,0 +1,159 @@
+import { parseEther } from 'ethers/lib/utils'
+import {
+ TestERC20__factory,
+ TestOracle2__factory,
+ TestUniswap__factory,
+ TestWrappedNativeToken__factory,
+ TokenPaymaster,
+ TokenPaymaster__factory,
+} from '../typechain'
+import { ethers } from 'hardhat'
+import { GasCheckCollector, GasChecker } from './GasChecker'
+import { Create2Factory } from '../src/Create2Factory'
+import { hexValue } from '@ethersproject/bytes'
+import {
+ OracleHelper as OracleHelperNamespace,
+ UniswapHelper as UniswapHelperNamespace,
+} from '../typechain/contracts/samples/TokenPaymaster'
+import { BigNumber } from 'ethers'
+import { createAccountOwner } from '../test/testutils'
+// const ethersSigner = ethers.provider.getSigner()
+
+context('Token Paymaster', function () {
+ this.timeout(60000)
+ const g = new GasChecker()
+
+ let paymasterAddress: string
+ before(async () => {
+ await GasCheckCollector.init()
+ const globalSigner = ethers.provider.getSigner()
+ const create2Factory = new Create2Factory(ethers.provider, globalSigner)
+
+ const ethersSigner = createAccountOwner()
+ await globalSigner.sendTransaction({ to: ethersSigner.getAddress(), value: parseEther('10') })
+
+ const minEntryPointBalance = (1e17).toString()
+ const initialPriceToken = 100000000 // USD per TOK
+ const initialPriceEther = 500000000 // USD per ETH
+ const priceDenominator = BigNumber.from(10).pow(26)
+
+ const tokenInit = await new TestERC20__factory(ethersSigner).getDeployTransaction(6)
+ const tokenAddress = await create2Factory.deploy(tokenInit, 0)
+ const token = TestERC20__factory.connect(tokenAddress, ethersSigner)
+
+ const wethInit = await new TestWrappedNativeToken__factory(ethersSigner).getDeployTransaction()
+ const wethAddress = await create2Factory.deploy(wethInit, 0)
+ const testUniswapInit = await new TestUniswap__factory(ethersSigner).getDeployTransaction(
+ wethAddress
+ )
+ const testUniswapAddress = await create2Factory.deploy(testUniswapInit, 0)
+
+ const tokenPaymasterConfig: TokenPaymaster.TokenPaymasterConfigStruct = {
+ priceMaxAge: 86400,
+ refundPostopCost: 40000,
+ minEntryPointBalance,
+ priceMarkup: priceDenominator.mul(15).div(10), // +50%
+ }
+
+ const nativeAssetOracleInit = await new TestOracle2__factory(ethersSigner).getDeployTransaction(
+ initialPriceEther,
+ 8
+ )
+ const nativeAssetOracleAddress = await create2Factory.deploy(
+ nativeAssetOracleInit,
+ 0,
+ 10_000_000
+ )
+ const tokenOracleInit = await new TestOracle2__factory(ethersSigner).getDeployTransaction(
+ initialPriceToken,
+ 8
+ )
+ const tokenOracleAddress = await create2Factory.deploy(tokenOracleInit, 0, 10_000_000)
+
+ const oracleHelperConfig: OracleHelperNamespace.OracleHelperConfigStruct = {
+ cacheTimeToLive: 100000000,
+ maxOracleRoundAge: 0,
+ nativeOracle: nativeAssetOracleAddress,
+ nativeOracleReverse: false,
+ priceUpdateThreshold: priceDenominator.mul(2).div(10), // +20%
+ tokenOracle: tokenOracleAddress,
+ tokenOracleReverse: false,
+ tokenToNativeOracle: false,
+ }
+
+ const uniswapHelperConfig: UniswapHelperNamespace.UniswapHelperConfigStruct = {
+ minSwapAmount: 1,
+ slippage: 5,
+ uniswapPoolFee: 3,
+ }
+
+ const owner = await ethersSigner.getAddress()
+
+ const paymasterInit = hexValue(
+ new TokenPaymaster__factory(ethersSigner).getDeployTransaction(
+ tokenAddress,
+ g.entryPoint().address,
+ wethAddress,
+ testUniswapAddress,
+ tokenPaymasterConfig,
+ oracleHelperConfig,
+ uniswapHelperConfig,
+ owner
+ ).data!
+ )
+ paymasterAddress = await create2Factory.deploy(paymasterInit, 0)
+ const paymaster = TokenPaymaster__factory.connect(paymasterAddress, ethersSigner)
+ await paymaster.addStake(1, { value: 1 })
+ await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') })
+ await paymaster.updateCachedPrice(true)
+ await g.createAccounts1(11)
+ await token.sudoMint(await ethersSigner.getAddress(), parseEther('20'))
+ await token.transfer(paymaster.address, parseEther('0.1'))
+ for (const address of g.createdAccounts) {
+ await token.transfer(address, parseEther('1'))
+ await token.sudoApprove(address, paymaster.address, ethers.constants.MaxUint256)
+ }
+
+ console.log('==addresses:', {
+ ethersSigner: await ethersSigner.getAddress(),
+ paymasterAddress,
+ nativeAssetOracleAddress,
+ tokenOracleAddress,
+ tokenAddress,
+ owner,
+ createdAccounts: g.createdAccounts,
+ })
+ })
+
+ it('token paymaster', async function () {
+ await g.addTestRow({
+ title: 'token paymaster',
+ count: 1,
+ paymaster: paymasterAddress,
+ diffLastGas: false,
+ })
+ await g.addTestRow({
+ title: 'token paymaster with diff',
+ count: 2,
+ paymaster: paymasterAddress,
+ diffLastGas: true,
+ })
+ })
+
+ it('token paymaster 10', async function () {
+ if (g.skipLong()) this.skip()
+
+ await g.addTestRow({
+ title: 'token paymaster',
+ count: 10,
+ paymaster: paymasterAddress,
+ diffLastGas: false,
+ })
+ await g.addTestRow({
+ title: 'token paymaster with diff',
+ count: 11,
+ paymaster: paymasterAddress,
+ diffLastGas: true,
+ })
+ })
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/GasChecker.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/GasChecker.ts
new file mode 100644
index 000000000..8a30d215a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/gascalc/GasChecker.ts
@@ -0,0 +1,459 @@
+// calculate gas usage of different bundle sizes
+import '../test/aa.init'
+import { defaultAbiCoder, hexConcat, parseEther } from 'ethers/lib/utils'
+import {
+ AddressZero,
+ checkForGeth,
+ createAddress,
+ createAccountOwner,
+ deployEntryPoint,
+ decodeRevertReason,
+} from '../test/testutils'
+import {
+ EntryPoint,
+ EntryPoint__factory,
+ SimpleAccountFactory,
+ SimpleAccountFactory__factory,
+ SimpleAccount__factory,
+} from '../typechain'
+import { BigNumberish, Wallet } from 'ethers'
+import hre from 'hardhat'
+import { fillSignAndPack, fillUserOp, packUserOp, signUserOp } from '../test/UserOp'
+import { TransactionReceipt } from '@ethersproject/abstract-provider'
+import { table, TableUserConfig } from 'table'
+import { Create2Factory } from '../src/Create2Factory'
+import * as fs from 'fs'
+import { SimpleAccountInterface } from '../typechain/contracts/samples/SimpleAccount'
+import { PackedUserOperation } from '../test/UserOperation'
+import { expect } from 'chai'
+
+const gasCheckerLogFile = './reports/gas-checker.txt'
+
+const ethers = hre.ethers
+const provider = hre.ethers.provider
+let ethersSigner = provider.getSigner()
+let lastGasUsed: number
+
+const minDepositOrBalance = parseEther('0.1')
+
+const getBalance = hre.ethers.provider.getBalance
+
+function range(n: number): number[] {
+ return Array(n)
+ .fill(0)
+ .map((val, index) => index)
+}
+
+interface GasTestInfo {
+ title: string
+ diffLastGas: boolean
+ paymaster: string
+ count: number
+ // address, or 'random' or 'self' (for account itself)
+ dest: string
+ destValue: BigNumberish
+ destCallData: string
+ beneficiary: string
+ gasPrice: number
+}
+
+export const DefaultGasTestInfo: Partial = {
+ dest: 'self', // destination is the account itself.
+ destValue: parseEther('0'),
+ destCallData: '0xb0d691fe', // entryPoint()
+ gasPrice: 10e9,
+}
+
+interface GasTestResult {
+ title: string
+ count: number
+ gasUsed: number // actual gas used
+ accountEst: number // estimateGas of the inner transaction (from EP to account)
+ gasDiff?: number // different from last test's gas used
+ receipt?: TransactionReceipt
+}
+
+/**
+ * singleton contract used by all GasChecker modules ("tests")
+ * init() static method -
+ * - create the singleton the first time (or return its existing instance)
+ * run
+ */
+
+// gas estimate of the "execFromSingleton" methods
+// we assume a given call signature has the same gas usage
+// (TODO: the estimate also depends on contract code. for test purposes, assume each contract implementation has different method signature)
+// at the end of the checks, we report the gas usage of all those method calls
+const gasEstimatePerExec: { [key: string]: { title: string; accountEst: number } } = {}
+
+/**
+ * helper contract to generate gas test.
+ * see runTest() method for "test template" info
+ * override for different account implementation:
+ * - accountInitCode() - the constructor code
+ * - accountExec() the account execution method.
+ */
+export class GasChecker {
+ accounts: { [account: string]: Wallet } = {}
+
+ accountOwner: Wallet
+
+ accountInterface: SimpleAccountInterface
+
+ constructor() {
+ this.accountOwner = createAccountOwner()
+ this.accountInterface = SimpleAccount__factory.createInterface()
+ void GasCheckCollector.init()
+ }
+
+ // generate the "exec" calldata for this account
+ accountExec(dest: string, value: BigNumberish, data: string): string {
+ return this.accountInterface.encodeFunctionData('execute', [dest, value, data])
+ }
+
+ // generate the account "creation code"
+ accountInitCode(factory: SimpleAccountFactory, salt: BigNumberish): string {
+ return hexConcat([
+ factory.address,
+ factory.interface.encodeFunctionData('createAccount', [this.accountOwner.address, salt]),
+ ])
+ }
+
+ createdAccounts = new Set()
+
+ /**
+ * create accounts up to this counter.
+ * make sure they all have balance.
+ * do nothing for account already created
+ * @param count
+ */
+ async createAccounts1(count: number): Promise {
+ const create2Factory = new Create2Factory(this.entryPoint().provider)
+ const factoryAddress = await create2Factory.deploy(
+ hexConcat([
+ SimpleAccountFactory__factory.bytecode,
+ defaultAbiCoder.encode(['address'], [this.entryPoint().address]),
+ ]),
+ 0,
+ 2885201
+ )
+ console.log('factaddr', factoryAddress)
+ const fact = SimpleAccountFactory__factory.connect(factoryAddress, ethersSigner)
+ // create accounts
+ const creationOps: PackedUserOperation[] = []
+ for (const n of range(count)) {
+ const salt = n
+ // const initCode = this.accountInitCode(fact, salt)
+
+ const addr = await fact.getAddress(this.accountOwner.address, salt)
+
+ if (!this.createdAccounts.has(addr)) {
+ // explicit call to fillUseROp with no "entryPoint", to make sure we manually fill everything and
+ // not attempt to fill from blockchain.
+ const op = signUserOp(
+ await fillUserOp({
+ sender: addr,
+ nonce: 0,
+ callGasLimit: 30000,
+ verificationGasLimit: 1000000,
+ // paymasterAndData: paymaster,
+ preVerificationGas: 1,
+ maxFeePerGas: 0,
+ }),
+ this.accountOwner,
+ this.entryPoint().address,
+ await provider.getNetwork().then((net) => net.chainId)
+ )
+ creationOps.push(packUserOp(op))
+ this.createdAccounts.add(addr)
+ }
+
+ this.accounts[addr] = this.accountOwner
+ // deploy if not already deployed.
+ await fact.createAccount(this.accountOwner.address, salt)
+ const accountBalance = await GasCheckCollector.inst.entryPoint.balanceOf(addr)
+ if (accountBalance.lte(minDepositOrBalance)) {
+ await GasCheckCollector.inst.entryPoint.depositTo(addr, {
+ value: minDepositOrBalance.mul(5),
+ })
+ }
+ }
+ await this.entryPoint().handleOps(creationOps, ethersSigner.getAddress())
+ }
+
+ /**
+ * helper: run a test scenario, and add a table row
+ * @param params - test parameters. missing values filled in from DefaultGasTestInfo
+ * note that 2 important params are methods: accountExec() and accountInitCode()
+ */
+ async addTestRow(params: Partial): Promise {
+ await GasCheckCollector.init()
+ GasCheckCollector.inst.addRow(await this.runTest(params))
+ }
+
+ /**
+ * run a single test scenario
+ * @param params - test parameters. missing values filled in from DefaultGasTestInfo
+ * note that 2 important params are methods: accountExec() and accountInitCode()
+ */
+ async runTest(params: Partial): Promise {
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ const info: GasTestInfo = { ...DefaultGasTestInfo, ...params } as GasTestInfo
+
+ console.debug('== running test count=', info.count)
+
+ // fill accounts up to this code.
+ await this.createAccounts1(info.count)
+
+ let accountEst: number = 0
+ const userOps = await Promise.all(
+ range(info.count)
+ .map((index) => Object.entries(this.accounts)[index])
+ .map(async ([account, accountOwner]) => {
+ const paymaster = info.paymaster
+
+ let { dest, destValue, destCallData } = info
+ if (dest === 'self') {
+ dest = account
+ } else if (dest === 'random') {
+ dest = createAddress()
+ const destBalance = await getBalance(dest)
+ if (destBalance.eq(0)) {
+ console.log('dest replenish', dest)
+ await ethersSigner.sendTransaction({ to: dest, value: 1 })
+ }
+ }
+ const accountExecFromEntryPoint = this.accountExec(dest, destValue, destCallData)
+
+ // remove the "dest" from the key to the saved estimations
+ // so we have a single estimation per method.
+ const estimateGasKey = this.accountExec(AddressZero, destValue, destCallData)
+
+ let est = gasEstimatePerExec[estimateGasKey]
+ // technically, each UserOp needs estimate - but we know they are all the same for each test.
+ if (est == null) {
+ const accountEst = (
+ await ethers.provider.estimateGas({
+ from: GasCheckCollector.inst.entryPoint.address,
+ to: account,
+ data: accountExecFromEntryPoint,
+ })
+ ).toNumber()
+ est = gasEstimatePerExec[estimateGasKey] = { accountEst, title: info.title }
+ }
+ // console.debug('== account est=', accountEst.toString())
+ accountEst = est.accountEst
+ const op = await fillSignAndPack(
+ {
+ sender: account,
+ callData: accountExecFromEntryPoint,
+ maxPriorityFeePerGas: info.gasPrice,
+ maxFeePerGas: info.gasPrice,
+ callGasLimit: accountEst,
+ verificationGasLimit: 1000000,
+ paymaster: paymaster,
+ paymasterVerificationGasLimit: 50000,
+ paymasterPostOpGasLimit: 50000,
+ preVerificationGas: 1,
+ },
+ accountOwner,
+ GasCheckCollector.inst.entryPoint
+ )
+ // const packed = packUserOp(op, false)
+ // console.log('== packed cost=', callDataCost(packed), packed)
+ return op
+ })
+ )
+
+ const txdata = GasCheckCollector.inst.entryPoint.interface.encodeFunctionData('handleOps', [
+ userOps,
+ info.beneficiary,
+ ])
+ console.log('=== encoded data=', txdata.length)
+ const gasEst = await GasCheckCollector.inst.entryPoint.estimateGas
+ .handleOps(userOps, info.beneficiary, {})
+ .catch((e) => {
+ const data = e.error?.data?.data ?? e.error?.data
+ if (data != null) {
+ const e1 = GasCheckCollector.inst.entryPoint.interface.parseError(data)
+ throw new Error(`${e1.name}(${e1.args?.toString()})`)
+ }
+ throw e
+ })
+ const ret = await GasCheckCollector.inst.entryPoint.handleOps(userOps, info.beneficiary, {
+ gasLimit: gasEst.mul(3).div(2),
+ })
+ const rcpt = await ret.wait()
+ const gasUsed = rcpt.gasUsed.toNumber()
+ const countSuccessOps = rcpt.events?.filter(
+ (e) => e.event === 'UserOperationEvent' && e.args?.success
+ ).length
+
+ rcpt.events
+ ?.filter((e) => e.event?.match(/PostOpRevertReason|UserOperationRevertReason/))
+ .find((e) => {
+ // console.log(e.event, e.args)
+ throw new Error(`${e.event}(${decodeRevertReason(e.args?.revertReason)})`)
+ })
+ // check for failure with no revert reason (e.g. OOG)
+ expect(countSuccessOps).to.eq(
+ userOps.length,
+ 'Some UserOps failed to execute (with no revert reason)'
+ )
+
+ console.debug('count', info.count, 'gasUsed', gasUsed)
+ const gasDiff = gasUsed - lastGasUsed
+ if (info.diffLastGas) {
+ console.debug('\tgas diff=', gasDiff)
+ }
+ lastGasUsed = gasUsed
+ console.debug('handleOps tx.hash=', rcpt.transactionHash)
+ const ret1: GasTestResult = {
+ count: info.count,
+ gasUsed,
+ accountEst,
+ title: info.title,
+ // receipt: rcpt
+ }
+ if (info.diffLastGas) {
+ ret1.gasDiff = gasDiff
+ }
+ console.debug(ret1)
+ return ret1
+ }
+
+ // helper methods to access the GasCheckCollector singleton
+ addRow(res: GasTestResult): void {
+ GasCheckCollector.inst.addRow(res)
+ }
+
+ entryPoint(): EntryPoint {
+ return GasCheckCollector.inst.entryPoint
+ }
+
+ skipLong(): boolean {
+ return process.env.SKIP_LONG != null
+ }
+}
+
+export class GasCheckCollector {
+ static inst: GasCheckCollector
+ static initPromise?: Promise
+
+ entryPoint: EntryPoint
+
+ static async init(): Promise {
+ if (this.inst == null) {
+ if (this.initPromise == null) {
+ this.initPromise = new GasCheckCollector()._init()
+ }
+ this.inst = await this.initPromise
+ }
+ }
+
+ async _init(entryPointAddressOrTest: string = 'test'): Promise {
+ console.log('signer=', await ethersSigner.getAddress())
+ DefaultGasTestInfo.beneficiary = createAddress()
+
+ const bal = await getBalance(ethersSigner.getAddress())
+ if (bal.gt(parseEther('100000000'))) {
+ console.log('DONT use geth miner.. use account 2 instead')
+ await checkForGeth()
+ ethersSigner = ethers.provider.getSigner(2)
+ }
+
+ if (entryPointAddressOrTest === 'test') {
+ this.entryPoint = await deployEntryPoint(provider)
+ } else {
+ this.entryPoint = EntryPoint__factory.connect(entryPointAddressOrTest, ethersSigner)
+ }
+
+ const tableHeaders = [
+ 'handleOps description ',
+ 'count',
+ 'total gasUsed',
+ 'per UserOp gas\n(delta for\none UserOp)',
+ // 'account.exec()\nestimateGas',
+ 'per UserOp overhead\n(compared to\naccount.exec())',
+ ]
+
+ this.initTable(tableHeaders)
+ return this
+ }
+
+ tableConfig: TableUserConfig
+ tabRows: any[]
+
+ /**
+ * initialize our formatted table.
+ * each header define the width of the column, so make sure to pad with spaces
+ * (we stream the table, so can't learn the content length)
+ */
+ initTable(tableHeaders: string[]): void {
+ console.log('inittable')
+
+ // multiline header - check the length of the longest line.
+ // function columnWidth (header: string): number {
+ // return Math.max(...header.split('\n').map(s => s.length))
+ // }
+
+ this.tableConfig = {
+ columnDefault: { alignment: 'right' },
+ columns: [{ alignment: 'left' }],
+ // columns: tableHeaders.map((header, index) => ({
+ // alignment: index == 0 ? 'left' : 'right',
+ // width: columnWidth(header)
+ // })),
+ // columnCount: tableHeaders.length
+ }
+ this.tabRows = [tableHeaders]
+ }
+
+ doneTable(): void {
+ fs.rmSync(gasCheckerLogFile, { force: true })
+ const write = (s: string): void => {
+ console.log(s)
+ fs.appendFileSync(gasCheckerLogFile, s + '\n')
+ }
+
+ write('== gas estimate of direct calling the account\'s "execute" method')
+ write(
+ ' the destination is "account.entryPoint()", which is known to be "hot" address used by this account'
+ )
+ write(
+ ' it little higher than EOA call: its an exec from entrypoint (or account owner) into account contract, verifying msg.sender and exec to target)'
+ )
+
+ write(
+ table(
+ Object.values(gasEstimatePerExec).map((row) => [
+ `gas estimate "${row.title}"`,
+ row.accountEst,
+ ]),
+ this.tableConfig
+ )
+ )
+
+ const tableOutput = table(this.tabRows, this.tableConfig)
+ write(tableOutput)
+ // process.exit(0)
+ }
+
+ addRow(res: GasTestResult): void {
+ const gasUsed = res.gasDiff != null ? '' : res.gasUsed // hide "total gasUsed" if there is a diff
+ const perOp = res.gasDiff != null ? res.gasDiff - res.accountEst : ''
+
+ this.tabRows.push([
+ res.title,
+ res.count,
+ gasUsed,
+ res.gasDiff ?? '',
+ // res.accountEst,
+ perOp,
+ ])
+ }
+}
+
+after(() => {
+ GasCheckCollector.inst.doneTable()
+})
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/hardhat.config.ts b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/hardhat.config.ts
new file mode 100644
index 000000000..e27408cb2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/hardhat.config.ts
@@ -0,0 +1,86 @@
+import '@nomiclabs/hardhat-waffle'
+import '@typechain/hardhat'
+import { HardhatUserConfig, task } from 'hardhat/config'
+import 'hardhat-deploy'
+import '@nomiclabs/hardhat-etherscan'
+
+import 'solidity-coverage'
+
+import * as fs from 'fs'
+
+const SALT = '0x90d8084deab30c2a37c45e8d47f49f2f7965183cb6990a98943ef94940681de3'
+process.env.SALT = process.env.SALT ?? SALT
+
+task('deploy', 'Deploy contracts').addFlag(
+ 'simpleAccountFactory',
+ 'deploy sample factory (by default, enabled only on localhost)'
+)
+
+const mnemonicFileName = process.env.MNEMONIC_FILE!
+let mnemonic = 'test '.repeat(11) + 'junk'
+if (fs.existsSync(mnemonicFileName)) {
+ mnemonic = fs.readFileSync(mnemonicFileName, 'ascii')
+}
+
+function getNetwork1(url: string): { url: string; accounts: { mnemonic: string } } {
+ return {
+ url,
+ accounts: { mnemonic },
+ }
+}
+
+function getNetwork(name: string): { url: string; accounts: { mnemonic: string } } {
+ return getNetwork1(`https://${name}.infura.io/v3/${process.env.INFURA_ID}`)
+ // return getNetwork1(`wss://${name}.infura.io/ws/v3/${process.env.INFURA_ID}`)
+}
+
+const optimizedComilerSettings = {
+ version: '0.8.23',
+ settings: {
+ optimizer: { enabled: true, runs: 1000000 },
+ viaIR: true,
+ },
+}
+
+// You need to export an object to set up your config
+// Go to https://hardhat.org/config/ to learn more
+
+const config: HardhatUserConfig = {
+ solidity: {
+ compilers: [
+ {
+ version: '0.8.23',
+ settings: {
+ optimizer: { enabled: true, runs: 1000000 },
+ },
+ },
+ ],
+ overrides: {
+ 'contracts/core/EntryPoint.sol': optimizedComilerSettings,
+ 'contracts/samples/SimpleAccount.sol': optimizedComilerSettings,
+ },
+ },
+ networks: {
+ dev: { url: 'http://localhost:8545' },
+ // github action starts localgeth service, for gas calculations
+ localgeth: { url: 'http://localgeth:8545' },
+ goerli: getNetwork('goerli'),
+ sepolia: getNetwork('sepolia'),
+ proxy: getNetwork1('http://localhost:8545'),
+ },
+ mocha: {
+ timeout: 10000,
+ },
+ // @ts-ignore
+ etherscan: {
+ apiKey: process.env.ETHERSCAN_API_KEY,
+ },
+}
+
+// coverage chokes on the "compilers" settings
+if (process.env.COVERAGE != null) {
+ // @ts-ignore
+ config.solidity = config.solidity.compilers[0]
+}
+
+export default config
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/package.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/package.json
new file mode 100644
index 000000000..045c6ad2c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/package.json
@@ -0,0 +1,71 @@
+{
+ "name": "accountabstraction",
+ "version": "0.7.0",
+ "description": "ERC-4337 Account Abstraction Implementation",
+ "scripts": {
+ "clean": "rm -rf cache artifacts typechain typechain-types",
+ "compile": "./scripts/hh-wrapper compile",
+ "tsc": "tsc",
+ "lint": "yarn compile && yarn run lint:sol && yarn run lint:js ",
+ "lint:js": "eslint -f unix .",
+ "lint-fix": "eslint -f unix . --fix",
+ "lint:sol": "solhint -f unix \"contracts/**/*.sol\" --max-warnings 0",
+ "gas-calc": "./scripts/gascalc",
+ "mocha-gascalc": "TS_NODE_TRANSPILE_ONLY=1 npx ts-mocha --bail gascalc/*",
+ "test": "./scripts/hh-wrapper test",
+ "coverage": "COVERAGE=1 hardhat coverage",
+ "deploy": "./scripts/hh-wrapper deploy",
+ "test-dev": "hardhat test --network dev",
+ "ci": "yarn compile && hardhat test && yarn run runop",
+ "ci-gas-calc": "yarn gas-calc && yarn check-gas-reports",
+ "check-gas-reports": "./scripts/check-gas-reports",
+ "runop": "hardhat run src/runop.ts "
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "@nomicfoundation/hardhat-chai-matchers": "^1.0.6",
+ "@nomiclabs/hardhat-ethers": "^2.0.2",
+ "@nomiclabs/hardhat-waffle": "^2.0.1",
+ "@typechain/ethers-v5": "^10.1.0",
+ "@types/chai": "^4.2.21",
+ "@types/node": "^16.4.12",
+ "@typescript-eslint/eslint-plugin": "^5.30.5",
+ "@typescript-eslint/parser": "^5.30.5",
+ "@uniswap/v3-periphery": "^1.4.3",
+ "chai": "^4.3.4",
+ "eslint": "^8.19.0",
+ "eslint-config-standard": "^17.0.0",
+ "eslint-config-standard-with-typescript": "^21.0.1",
+ "eslint-plugin-import": "^2.26.0",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-promise": "^6.0.0",
+ "eslint-plugin-standard": "^5.0.0",
+ "ethereum-waffle": "^3.4.0",
+ "ethers": "^5.4.2",
+ "hardhat": "^2.17.2",
+ "solhint": "^3.3.7",
+ "ts-generator": "^0.1.1",
+ "ts-mocha": "^10.0.0",
+ "ts-node": "^10.1.0",
+ "typechain": "^8.1.0"
+ },
+ "dependencies": {
+ "@nomiclabs/hardhat-etherscan": "^2.1.6",
+ "@openzeppelin/contracts": "^5.0.2",
+ "@thehubbleproject/bls": "^0.5.1",
+ "@typechain/hardhat": "^2.3.0",
+ "@types/debug": "^4.1.12",
+ "@types/mocha": "^9.0.0",
+ "debug": "^4.3.4",
+ "ethereumjs-util": "^7.1.0",
+ "ethereumjs-wallet": "^1.0.1",
+ "hardhat-deploy": "^0.11.23",
+ "hardhat-deploy-ethers": "^0.3.0-beta.11",
+ "solidity-coverage": "^0.8.4",
+ "source-map-support": "^0.5.19",
+ "table": "^6.8.0",
+ "typescript": "^4.3.5"
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/reports/gas-checker.txt b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/reports/gas-checker.txt
new file mode 100644
index 000000000..692322bf7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/reports/gas-checker.txt
@@ -0,0 +1,55 @@
+== gas estimate of direct calling the account's "execute" method
+ the destination is "account.entryPoint()", which is known to be "hot" address used by this account
+ it little higher than EOA call: its an exec from entrypoint (or account owner) into account contract, verifying msg.sender and exec to target)
+╔══════════════════════════╤════════╗
+║ gas estimate "simple" │ 28979 ║
+╟──────────────────────────┼────────╢
+║ gas estimate "big tx 5k" │ 125224 ║
+╚══════════════════════════╧════════╝
+
+╔════════════════════════════════╤═══════╤═══════════════╤════════════════╤═════════════════════╗
+║ handleOps description │ count │ total gasUsed │ per UserOp gas │ per UserOp overhead ║
+║ │ │ │ (delta for │ (compared to ║
+║ │ │ │ one UserOp) │ account.exec()) ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple │ 1 │ 79994 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple - diff from previous │ 2 │ │ 42192 │ 13213 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple │ 10 │ 459921 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple - diff from previous │ 11 │ │ 42223 │ 13244 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple paymaster │ 1 │ 86113 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple paymaster with diff │ 2 │ │ 41024 │ 12045 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple paymaster │ 10 │ 455444 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ simple paymaster with diff │ 11 │ │ 41088 │ 12109 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ big tx 5k │ 1 │ 181026 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ big tx - diff from previous │ 2 │ │ 142714 │ 17490 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ big tx 5k │ 10 │ 1465443 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ big tx - diff from previous │ 11 │ │ 142686 │ 17462 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ paymaster+postOp │ 1 │ 87712 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ paymaster+postOp with diff │ 2 │ │ 42671 │ 13692 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ paymaster+postOp │ 10 │ 471754 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ paymaster+postOp with diff │ 11 │ │ 42728 │ 13749 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ token paymaster │ 1 │ 128777 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ token paymaster with diff │ 2 │ │ 66386 │ 37407 ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ token paymaster │ 10 │ 726504 │ │ ║
+╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
+║ token paymaster with diff │ 11 │ │ 66394 │ 37415 ║
+╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/check-gas-reports b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/check-gas-reports
new file mode 100644
index 000000000..d0af47d1b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/check-gas-reports
@@ -0,0 +1,17 @@
+#!/bin/bash
+# make sure gas reports are checked in with this commit
+# dump report diff
+# exit with "1" if there is a diff, zero if no diff
+
+folder=${1:-reports}
+git diff --color=always $folder
+git diff ${folder} | grep -q .
+
+if [ "$?" == 1 ]; then
+ #diff with no error - ok
+ exit
+else
+ echo ERROR: found above unchecked reports.
+ exit 1
+fi
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/docker-gascalc b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/docker-gascalc
new file mode 100644
index 000000000..05c0eb274
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/docker-gascalc
@@ -0,0 +1,7 @@
+# run "yarn gas-calc" using geth with docker.
+# (if you have geth running on localhost:8545, its faster with "HARDHAT_NETWORK=dev yarn gas-calc")
+docker-compose -f `dirname $0`/docker-gascalc.yml up --abort-on-container-exit
+exit=$?
+docker-compose -f `dirname $0`/docker-gascalc.yml down
+exit $exit
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/docker-gascalc.yml b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/docker-gascalc.yml
new file mode 100644
index 000000000..9dd3901fc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/docker-gascalc.yml
@@ -0,0 +1,20 @@
+version: '2'
+
+services:
+ test:
+ image: node:18
+ container_name: gascalc
+ depends_on:
+ - localgeth
+ volumes:
+ - ..:/app
+ working_dir: /app
+ restart: "no"
+ environment:
+ - HARDHAT_NETWORK=localgeth
+ command: "yarn mocha-gascalc"
+
+ #configuration is a copy of github/.workflows/build.xml
+ localgeth:
+ image: dtr22/geth-dev
+ container_name: localgeth
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/gascalc b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/gascalc
new file mode 100644
index 000000000..b82f5327c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/gascalc
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# run gascalc, assuming "geth" is running on localhost, port 8545
+cd `dirname $0`/..
+function getClientVersion() {
+ curl -m 1 -s -d '{"method":"web3_clientVersion","params":[],"id":1234,"jsonrpc":"2.0"}' -H content-type:application/json localhost:8545
+}
+
+if [[ `getClientVersion` =~ "Geth" ]]; then
+ echo Using GETH on localhost:8545
+ HARDHAT_NETWORK=dev yarn mocha-gascalc
+else
+ echo No GETH running on localhost:8545. Using docker..
+ ./scripts/docker-gascalc
+fi
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/hh-wrapper b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/hh-wrapper
new file mode 100644
index 000000000..ada7d62db
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/hh-wrapper
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+set -euo pipefail
+export FORCE_COLOR=1
+hardhat "$@" 2>&1 | `dirname $0`/solcErrors
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/postpack-contracts-package.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/postpack-contracts-package.sh
new file mode 100644
index 000000000..6e1b23980
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/postpack-contracts-package.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -xe
+#echo postpack for "contracts" package
+cd `dirname $0`/..
+pwd
+rm -rf contracts/artifacts
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/prepack-contracts-package.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/prepack-contracts-package.sh
new file mode 100644
index 000000000..eac8c94b1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/prepack-contracts-package.sh
@@ -0,0 +1,17 @@
+#!/bin/bash -xe
+#echo prepack for "contracts" package
+
+cd `dirname $0`/..
+pwd
+if git status contracts | grep -v 'nothing to commit'|tee /dev/stderr |grep -q Untracked; then
+ exit 1
+fi
+
+yarn clean
+yarn compile
+cd contracts
+
+rm -rf artifacts
+
+mkdir -p artifacts
+cp `find ../artifacts/contracts -type f | grep -v -E 'test|Test|dbg|bls|IOracle'` artifacts/
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/sample-script.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/sample-script.js
new file mode 100644
index 000000000..a2885d539
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/account-abstraction/scripts/sample-script.js
@@ -0,0 +1,32 @@
+// We require the Hardhat Runtime Environment explicitly here. This is optional
+// but useful for running the script in a standalone fashion through `node
+
+
+++++
+
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/contract.hbs b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/contract.hbs
new file mode 100644
index 000000000..aaca0a3cc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/contract.hbs
@@ -0,0 +1,137 @@
+{{#each items}}
+:{{name}}: pass:normal[xref:#{{anchor}}[`++{{name}}++`]]
+{{/each}}
+
+[.contract]
+[[{{anchor}}]]
+=== `++{{name}}++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v{{oz-version}}/{{__item_context.file.absolutePath}}[{github-icon},role=heading-link]
+
+[.hljs-theme-light.nopadding]
+```solidity
+import "@openzeppelin/{{__item_context.file.absolutePath}}";
+```
+
+{{{natspec.dev}}}
+
+{{#if modifiers}}
+[.contract-index]
+.Modifiers
+--
+{{#each modifiers}}
+* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
+{{/each}}
+--
+{{/if}}
+
+{{#if has-functions}}
+[.contract-index]
+.Functions
+--
+{{#each inherited-functions}}
+{{#unless @first}}
+[.contract-subindex-inherited]
+.{{contract.name}}
+{{/unless}}
+{{#each functions}}
+* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
+{{/each}}
+
+{{/each}}
+--
+{{/if}}
+
+{{#if has-events}}
+[.contract-index]
+.Events
+--
+{{#each inheritance}}
+{{#unless @first}}
+[.contract-subindex-inherited]
+.{{name}}
+{{/unless}}
+{{#each events}}
+* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
+{{/each}}
+
+{{/each}}
+--
+{{/if}}
+
+{{#if has-errors}}
+[.contract-index]
+.Errors
+--
+{{#each inheritance}}
+{{#unless @first}}
+[.contract-subindex-inherited]
+.{{name}}
+{{/unless}}
+{{#each errors}}
+* {xref-{{anchor~}} }[`++{{name}}({{names params}})++`]
+{{/each}}
+
+{{/each}}
+--
+{{/if}}
+
+{{#if has-internal-variables}}
+[.contract-index]
+.Internal Variables
+--
+{{#each inheritance}}
+{{#unless @first}}
+[.contract-subindex-inherited]
+.{{name}}
+{{/unless}}
+{{#each internal-variables}}
+* {xref-{{anchor~}} }[`++{{typeDescriptions.typeString}} {{#if constant}}constant{{/if}} {{name}}++`]
+{{/each}}
+
+{{/each}}
+--
+{{/if}}
+
+{{#each modifiers}}
+[.contract-item]
+[[{{anchor}}]]
+==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}})++` [.item-kind]#modifier#
+
+{{{natspec.dev}}}
+
+{{/each}}
+
+{{#each functions}}
+[.contract-item]
+[[{{anchor}}]]
+==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}}){{#if returns2}} → {{typed-params returns2}}{{/if}}++` [.item-kind]#{{visibility}}#
+
+{{{natspec.dev}}}
+
+{{/each}}
+
+{{#each events}}
+[.contract-item]
+[[{{anchor}}]]
+==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}})++` [.item-kind]#event#
+
+{{{natspec.dev}}}
+
+{{/each}}
+
+{{#each errors}}
+[.contract-item]
+[[{{anchor}}]]
+==== `[.contract-item-name]#++{{name}}++#++({{typed-params params}})++` [.item-kind]#error#
+
+{{{natspec.dev}}}
+
+{{/each}}
+
+{{#each internal-variables}}
+[.contract-item]
+[[{{anchor}}]]
+==== `{{typeDescriptions.typeString}} [.contract-item-name]#++{{name}}++#` [.item-kind]#internal{{#if constant}} constant{{/if}}#
+
+{{{natspec.dev}}}
+
+{{/each}}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/helpers.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/helpers.js
new file mode 100644
index 000000000..1b6383549
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/helpers.js
@@ -0,0 +1,46 @@
+const { version } = require('../../package.json');
+
+module.exports['oz-version'] = () => version;
+
+module.exports['readme-path'] = opts => {
+ return 'contracts/' + opts.data.root.id.replace(/\.adoc$/, '') + '/README.adoc';
+};
+
+module.exports.names = params => params?.map(p => p.name).join(', ');
+
+module.exports['typed-params'] = params => {
+ return params?.map(p => `${p.type}${p.indexed ? ' indexed' : ''}${p.name ? ' ' + p.name : ''}`).join(', ');
+};
+
+const slug = (module.exports.slug = str => {
+ if (str === undefined) {
+ throw new Error('Missing argument');
+ }
+ return str.replace(/\W/g, '-');
+});
+
+const linksCache = new WeakMap();
+
+function getAllLinks(items) {
+ if (linksCache.has(items)) {
+ return linksCache.get(items);
+ }
+ const res = {};
+ linksCache.set(items, res);
+ for (const item of items) {
+ res[`xref-${item.anchor}`] = `xref:${item.__item_context.page}#${item.anchor}`;
+ res[slug(item.fullName)] = `pass:normal[xref:${item.__item_context.page}#${item.anchor}[\`${item.fullName}\`]]`;
+ }
+ return res;
+}
+
+module.exports['with-prelude'] = opts => {
+ const links = getAllLinks(opts.data.site.items);
+ const contents = opts.fn();
+ const neededLinks = contents
+ .match(/\{[-._a-z0-9]+\}/gi)
+ .map(m => m.replace(/^\{(.+)\}$/, '$1'))
+ .filter(k => k in links);
+ const prelude = neededLinks.map(k => `:${k}: ${links[k]}`).join('\n');
+ return prelude + '\n' + contents;
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/page.hbs b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/page.hbs
new file mode 100644
index 000000000..cab050acb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/page.hbs
@@ -0,0 +1,4 @@
+:github-icon: pass:[ ]
+{{#with-prelude}}
+{{readme (readme-path)}}
+{{/with-prelude}}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/properties.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/properties.js
new file mode 100644
index 000000000..52eebac54
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/docs/templates/properties.js
@@ -0,0 +1,72 @@
+const { isNodeType, findAll } = require('solidity-ast/utils');
+const { slug } = require('./helpers');
+
+module.exports.anchor = function anchor({ item, contract }) {
+ let res = '';
+ if (contract) {
+ res += contract.name + '-';
+ }
+ res += item.name;
+ if ('parameters' in item) {
+ const signature = item.parameters.parameters.map(v => v.typeName.typeDescriptions.typeString).join(',');
+ res += slug('(' + signature + ')');
+ }
+ if (isNodeType('VariableDeclaration', item)) {
+ res += '-' + slug(item.typeName.typeDescriptions.typeString);
+ }
+ return res;
+};
+
+module.exports.inheritance = function ({ item, build }) {
+ if (!isNodeType('ContractDefinition', item)) {
+ throw new Error('used inherited-items on non-contract');
+ }
+
+ return item.linearizedBaseContracts
+ .map(id => build.deref('ContractDefinition', id))
+ .filter((c, i) => c.name !== 'Context' || i === 0);
+};
+
+module.exports['has-functions'] = function ({ item }) {
+ return item.inheritance.some(c => c.functions.length > 0);
+};
+
+module.exports['has-events'] = function ({ item }) {
+ return item.inheritance.some(c => c.events.length > 0);
+};
+
+module.exports['has-errors'] = function ({ item }) {
+ return item.inheritance.some(c => c.errors.length > 0);
+};
+
+module.exports['internal-variables'] = function ({ item }) {
+ return item.variables.filter(({ visibility }) => visibility === 'internal');
+};
+
+module.exports['has-internal-variables'] = function ({ item }) {
+ return module.exports['internal-variables']({ item }).length > 0;
+};
+
+module.exports.functions = function ({ item }) {
+ return [
+ ...[...findAll('FunctionDefinition', item)].filter(f => f.visibility !== 'private'),
+ ...[...findAll('VariableDeclaration', item)].filter(f => f.visibility === 'public'),
+ ];
+};
+
+module.exports.returns2 = function ({ item }) {
+ if (isNodeType('VariableDeclaration', item)) {
+ return [{ type: item.typeDescriptions.typeString }];
+ } else {
+ return item.returns;
+ }
+};
+
+module.exports['inherited-functions'] = function ({ item }) {
+ const { inheritance } = item;
+ const baseFunctions = new Set(inheritance.flatMap(c => c.functions.flatMap(f => f.baseFunctions ?? [])));
+ return inheritance.map((contract, i) => ({
+ contract,
+ functions: contract.functions.filter(f => !baseFunctions.has(f.id) && (f.name !== 'constructor' || i === 0)),
+ }));
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/eslint.config.mjs b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/eslint.config.mjs
new file mode 100644
index 000000000..00fcc95bb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/eslint.config.mjs
@@ -0,0 +1,26 @@
+import js from '@eslint/js';
+import { includeIgnoreFile } from '@eslint/compat';
+import prettier from 'eslint-config-prettier';
+import globals from 'globals';
+import path from 'path';
+
+export default [
+ js.configs.recommended,
+ prettier,
+ {
+ languageOptions: {
+ ecmaVersion: 2022,
+ globals: {
+ ...globals.browser,
+ ...globals.mocha,
+ ...globals.node,
+ artifacts: 'readonly',
+ contract: 'readonly',
+ web3: 'readonly',
+ extendEnvironment: 'readonly',
+ expect: 'readonly',
+ },
+ },
+ },
+ includeIgnoreFile(path.resolve(import.meta.dirname, '.gitignore')),
+];
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/foundry.toml b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/foundry.toml
new file mode 100644
index 000000000..78dd07812
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/foundry.toml
@@ -0,0 +1,15 @@
+[profile.default]
+solc_version = '0.8.24'
+evm_version = 'cancun'
+optimizer = true
+optimizer-runs = 200
+src = 'contracts'
+out = 'out'
+libs = ['node_modules', 'lib']
+test = 'test'
+cache_path = 'cache_forge'
+fs_permissions = [{ access = "read", path = "./test/bin" }]
+
+[fuzz]
+runs = 5000
+max_test_rejects = 150000
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/fv-requirements.txt b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/fv-requirements.txt
new file mode 100644
index 000000000..608b4de24
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/fv-requirements.txt
@@ -0,0 +1,4 @@
+certora-cli==4.13.1
+# File uses a custom name (fv-requirements.txt) so that it isn't picked by Netlify's build
+# whose latest Python version is 0.3.8, incompatible with most recent versions of Halmos
+halmos==0.2.0
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat.config.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat.config.js
new file mode 100644
index 000000000..d39d3d073
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat.config.js
@@ -0,0 +1,124 @@
+/// ENVVAR
+// - COMPILER: compiler version (default: 0.8.24)
+// - SRC: contracts folder to compile (default: contracts)
+// - RUNS: number of optimization runs (default: 200)
+// - IR: enable IR compilation (default: false)
+// - COVERAGE: enable coverage report (default: false)
+// - GAS: enable gas report (default: false)
+// - COINMARKETCAP: coinmarketcap api key for USD value in gas report
+// - CI: output gas report to file instead of stdout
+
+const fs = require('fs');
+const path = require('path');
+
+const { argv } = require('yargs/yargs')()
+ .env('')
+ .options({
+ // Compilation settings
+ compiler: {
+ alias: 'compileVersion',
+ type: 'string',
+ default: '0.8.24',
+ },
+ src: {
+ alias: 'source',
+ type: 'string',
+ default: 'contracts',
+ },
+ runs: {
+ alias: 'optimizationRuns',
+ type: 'number',
+ default: 200,
+ },
+ ir: {
+ alias: 'enableIR',
+ type: 'boolean',
+ default: false,
+ },
+ evm: {
+ alias: 'evmVersion',
+ type: 'string',
+ default: 'cancun',
+ },
+ // Extra modules
+ coverage: {
+ type: 'boolean',
+ default: false,
+ },
+ gas: {
+ alias: 'enableGasReport',
+ type: 'boolean',
+ default: false,
+ },
+ coinmarketcap: {
+ alias: 'coinmarketcapApiKey',
+ type: 'string',
+ },
+ });
+
+require('@nomicfoundation/hardhat-chai-matchers');
+require('@nomicfoundation/hardhat-ethers');
+require('hardhat-exposed');
+require('hardhat-gas-reporter');
+require('hardhat-ignore-warnings');
+require('solidity-coverage');
+require('solidity-docgen');
+
+for (const f of fs.readdirSync(path.join(__dirname, 'hardhat'))) {
+ require(path.join(__dirname, 'hardhat', f));
+}
+
+/**
+ * @type import('hardhat/config').HardhatUserConfig
+ */
+module.exports = {
+ solidity: {
+ version: argv.compiler,
+ settings: {
+ optimizer: {
+ enabled: true,
+ runs: argv.runs,
+ },
+ evmVersion: argv.evm,
+ viaIR: argv.ir,
+ outputSelection: { '*': { '*': ['storageLayout'] } },
+ },
+ },
+ warnings: {
+ 'contracts-exposed/**/*': {
+ 'code-size': 'off',
+ 'initcode-size': 'off',
+ },
+ '*': {
+ 'code-size': true,
+ 'unused-param': !argv.coverage, // coverage causes unused-param warnings
+ 'transient-storage': false,
+ default: 'error',
+ },
+ },
+ networks: {
+ hardhat: {
+ hardfork: argv.evm,
+ // Exposed contracts often exceed the maximum contract size. For normal contract,
+ // we rely on the `code-size` compiler warning, that will cause a compilation error.
+ allowUnlimitedContractSize: true,
+ initialBaseFeePerGas: argv.coverage ? 0 : undefined,
+ },
+ },
+ exposed: {
+ imports: true,
+ initializers: true,
+ exclude: ['vendor/**/*', '**/*WithInit.sol'],
+ },
+ gasReporter: {
+ enabled: argv.gas,
+ showMethodSig: true,
+ includeBytecodeInJSON: true,
+ currency: 'USD',
+ coinmarketcap: argv.coinmarketcap,
+ },
+ paths: {
+ sources: argv.src,
+ },
+ docgen: require('./docs/config'),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/async-test-sanity.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/async-test-sanity.js
new file mode 100644
index 000000000..c05e5bd48
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/async-test-sanity.js
@@ -0,0 +1,3 @@
+process.on('unhandledRejection', reason => {
+ throw new Error(reason);
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/env-artifacts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/env-artifacts.js
new file mode 100644
index 000000000..e97ae6468
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/env-artifacts.js
@@ -0,0 +1,29 @@
+const { HardhatError } = require('hardhat/internal/core/errors');
+
+function isExpectedError(e, suffix) {
+ // HH700: Artifact not found - from https://hardhat.org/hardhat-runner/docs/errors#HH700
+ return HardhatError.isHardhatError(e) && e.number === 700 && suffix !== '';
+}
+
+// Modifies the artifact require functions so that instead of X it loads the XUpgradeable contract.
+// This allows us to run the same test suite on both the original and the transpiled and renamed Upgradeable contracts.
+extendEnvironment(hre => {
+ const suffixes = ['UpgradeableWithInit', 'Upgradeable', ''];
+
+ // Ethers
+ const originalReadArtifact = hre.artifacts.readArtifact;
+ hre.artifacts.readArtifact = async function (name) {
+ for (const suffix of suffixes) {
+ try {
+ return await originalReadArtifact.call(this, name + suffix);
+ } catch (e) {
+ if (isExpectedError(e, suffix)) {
+ continue;
+ } else {
+ throw e;
+ }
+ }
+ }
+ throw new Error('Unreachable');
+ };
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/ignore-unreachable-warnings.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/ignore-unreachable-warnings.js
new file mode 100644
index 000000000..8e3e34340
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/ignore-unreachable-warnings.js
@@ -0,0 +1,45 @@
+// Warnings about unreachable code are emitted with a source location that corresponds to the unreachable code.
+// We have some testing contracts that purposely cause unreachable code, but said code is in the library contracts, and
+// with hardhat-ignore-warnings we are not able to selectively ignore them without potentially ignoring relevant
+// warnings that we don't want to miss.
+// Thus, we need to handle these warnings separately. We force Hardhat to compile them in a separate compilation job and
+// then ignore the warnings about unreachable code that come from that compilation job.
+
+const { task } = require('hardhat/config');
+const {
+ TASK_COMPILE_SOLIDITY_GET_COMPILATION_JOB_FOR_FILE,
+ TASK_COMPILE_SOLIDITY_COMPILE,
+} = require('hardhat/builtin-tasks/task-names');
+
+const marker = Symbol('unreachable');
+const markedCache = new WeakMap();
+
+task(TASK_COMPILE_SOLIDITY_GET_COMPILATION_JOB_FOR_FILE, async (params, _, runSuper) => {
+ const job = await runSuper(params);
+ // If the file is in the unreachable directory, we make a copy of the config and mark it, which will cause it to get
+ // compiled separately (along with the other marked files).
+ if (params.file.sourceName.startsWith('contracts/mocks/') && /\bunreachable\b/.test(params.file.sourceName)) {
+ const originalConfig = job.solidityConfig;
+ let markedConfig = markedCache.get(originalConfig);
+ if (markedConfig === undefined) {
+ markedConfig = { ...originalConfig, [marker]: true };
+ markedCache.set(originalConfig, markedConfig);
+ }
+ job.solidityConfig = markedConfig;
+ }
+ return job;
+});
+
+const W_UNREACHABLE_CODE = '5740';
+
+task(TASK_COMPILE_SOLIDITY_COMPILE, async (params, _, runSuper) => {
+ const marked = params.compilationJob.solidityConfig[marker];
+ const result = await runSuper(params);
+ if (marked) {
+ result.output = {
+ ...result.output,
+ errors: result.output.errors?.filter(e => e.severity !== 'warning' || e.errorCode !== W_UNREACHABLE_CODE),
+ };
+ }
+ return result;
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/remappings.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/remappings.js
new file mode 100644
index 000000000..cd9984d44
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/remappings.js
@@ -0,0 +1,18 @@
+const fs = require('fs');
+const { task } = require('hardhat/config');
+const { TASK_COMPILE_GET_REMAPPINGS } = require('hardhat/builtin-tasks/task-names');
+
+task(TASK_COMPILE_GET_REMAPPINGS).setAction((taskArgs, env, runSuper) =>
+ runSuper().then(remappings =>
+ Object.assign(
+ remappings,
+ Object.fromEntries(
+ fs
+ .readFileSync('remappings.txt', 'utf-8')
+ .split('\n')
+ .filter(Boolean)
+ .map(line => line.trim().split('=')),
+ ),
+ ),
+ ),
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/skip-foundry-tests.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/skip-foundry-tests.js
new file mode 100644
index 000000000..965ba37c3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/skip-foundry-tests.js
@@ -0,0 +1,6 @@
+const { subtask } = require('hardhat/config');
+const { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } = require('hardhat/builtin-tasks/task-names');
+
+subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(async (_, __, runSuper) =>
+ (await runSuper()).filter(path => !path.endsWith('.t.sol')),
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/task-test-get-files.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/task-test-get-files.js
new file mode 100644
index 000000000..108f40a42
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/hardhat/task-test-get-files.js
@@ -0,0 +1,25 @@
+const { internalTask } = require('hardhat/config');
+const { TASK_TEST_GET_TEST_FILES } = require('hardhat/builtin-tasks/task-names');
+
+// Modifies `hardhat test` to skip the proxy tests after proxies are removed by the transpiler for upgradeability.
+
+internalTask(TASK_TEST_GET_TEST_FILES).setAction(async (args, hre, runSuper) => {
+ const path = require('path');
+ const { promises: fs } = require('fs');
+
+ const hasProxies = await fs
+ .access(path.join(hre.config.paths.sources, 'proxy/Proxy.sol'))
+ .then(() => true)
+ .catch(() => false);
+
+ const ignoredIfProxy = [
+ 'proxy/beacon/BeaconProxy.test.js',
+ 'proxy/beacon/UpgradeableBeacon.test.js',
+ 'proxy/ERC1967/ERC1967Proxy.test.js',
+ 'proxy/transparent/ProxyAdmin.test.js',
+ 'proxy/transparent/TransparentUpgradeableProxy.test.js',
+ 'proxy/utils/UUPSUpgradeable.test.js',
+ ].map(p => path.join(hre.config.paths.tests, p));
+
+ return (await runSuper(args)).filter(file => hasProxies || !ignoredIfProxy.includes(file));
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/ERC4626.prop.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/ERC4626.prop.sol
new file mode 100644
index 000000000..c34512baa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/ERC4626.prop.sol
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: AGPL-3.0
+pragma solidity >=0.8.0 <0.9.0;
+
+import "forge-std/Test.sol";
+
+// TODO: use interface provided by forge-std v1.0.0 or later
+// import {IERC20} from "forge-std/interfaces/IERC20.sol";
+interface IERC20 {
+ event Transfer(address indexed from, address indexed to, uint value);
+ event Approval(address indexed owner, address indexed spender, uint value);
+ function totalSupply() external view returns (uint);
+ function balanceOf(address account) external view returns (uint);
+ function transfer(address to, uint amount) external returns (bool);
+ function allowance(address owner, address spender) external view returns (uint);
+ function approve(address spender, uint amount) external returns (bool);
+ function transferFrom(address from, address to, uint amount) external returns (bool);
+}
+
+// TODO: use interface provided by forge-std v1.0.0 or later
+// import {IERC4626} from "forge-std/interfaces/IERC4626.sol";
+interface IERC4626 is IERC20 {
+ event Deposit(address indexed caller, address indexed owner, uint assets, uint shares);
+ event Withdraw(address indexed caller, address indexed receiver, address indexed owner, uint assets, uint shares);
+ function asset() external view returns (address assetTokenAddress);
+ function totalAssets() external view returns (uint totalManagedAssets);
+ function convertToShares(uint assets) external view returns (uint shares);
+ function convertToAssets(uint shares) external view returns (uint assets);
+ function maxDeposit(address receiver) external view returns (uint maxAssets);
+ function previewDeposit(uint assets) external view returns (uint shares);
+ function deposit(uint assets, address receiver) external returns (uint shares);
+ function maxMint(address receiver) external view returns (uint maxShares);
+ function previewMint(uint shares) external view returns (uint assets);
+ function mint(uint shares, address receiver) external returns (uint assets);
+ function maxWithdraw(address owner) external view returns (uint maxAssets);
+ function previewWithdraw(uint assets) external view returns (uint shares);
+ function withdraw(uint assets, address receiver, address owner) external returns (uint shares);
+ function maxRedeem(address owner) external view returns (uint maxShares);
+ function previewRedeem(uint shares) external view returns (uint assets);
+ function redeem(uint shares, address receiver, address owner) external returns (uint assets);
+}
+
+abstract contract ERC4626Prop is Test {
+ uint internal _delta_;
+
+ address internal _underlying_;
+ address internal _vault_;
+
+ bool internal _vaultMayBeEmpty;
+ bool internal _unlimitedAmount;
+
+ //
+ // asset
+ //
+
+ // asset
+ // "MUST NOT revert."
+ function prop_asset(address caller) public {
+ vm.prank(caller); IERC4626(_vault_).asset();
+ }
+
+ // totalAssets
+ // "MUST NOT revert."
+ function prop_totalAssets(address caller) public {
+ vm.prank(caller); IERC4626(_vault_).totalAssets();
+ }
+
+ //
+ // convert
+ //
+
+ // convertToShares
+ // "MUST NOT show any variations depending on the caller."
+ function prop_convertToShares(address caller1, address caller2, uint assets) public {
+ vm.prank(caller1); uint res1 = vault_convertToShares(assets); // "MAY revert due to integer overflow caused by an unreasonably large input."
+ vm.prank(caller2); uint res2 = vault_convertToShares(assets); // "MAY revert due to integer overflow caused by an unreasonably large input."
+ assertEq(res1, res2);
+ }
+
+ // convertToAssets
+ // "MUST NOT show any variations depending on the caller."
+ function prop_convertToAssets(address caller1, address caller2, uint shares) public {
+ vm.prank(caller1); uint res1 = vault_convertToAssets(shares); // "MAY revert due to integer overflow caused by an unreasonably large input."
+ vm.prank(caller2); uint res2 = vault_convertToAssets(shares); // "MAY revert due to integer overflow caused by an unreasonably large input."
+ assertEq(res1, res2);
+ }
+
+ //
+ // deposit
+ //
+
+ // maxDeposit
+ // "MUST NOT revert."
+ function prop_maxDeposit(address caller, address receiver) public {
+ vm.prank(caller); IERC4626(_vault_).maxDeposit(receiver);
+ }
+
+ // previewDeposit
+ // "MUST return as close to and no more than the exact amount of Vault
+ // shares that would be minted in a deposit call in the same transaction.
+ // I.e. deposit should return the same or more shares as previewDeposit if
+ // called in the same transaction."
+ function prop_previewDeposit(address caller, address receiver, address other, uint assets) public {
+ vm.prank(other); uint sharesPreview = vault_previewDeposit(assets); // "MAY revert due to other conditions that would also cause deposit to revert."
+ vm.prank(caller); uint sharesActual = vault_deposit(assets, receiver);
+ assertApproxGeAbs(sharesActual, sharesPreview, _delta_);
+ }
+
+ // deposit
+ function prop_deposit(address caller, address receiver, uint assets) public {
+ uint oldCallerAsset = IERC20(_underlying_).balanceOf(caller);
+ uint oldReceiverShare = IERC20(_vault_).balanceOf(receiver);
+ uint oldAllowance = IERC20(_underlying_).allowance(caller, _vault_);
+
+ vm.prank(caller); uint shares = vault_deposit(assets, receiver);
+
+ uint newCallerAsset = IERC20(_underlying_).balanceOf(caller);
+ uint newReceiverShare = IERC20(_vault_).balanceOf(receiver);
+ uint newAllowance = IERC20(_underlying_).allowance(caller, _vault_);
+
+ assertApproxEqAbs(newCallerAsset, oldCallerAsset - assets, _delta_, "asset"); // NOTE: this may fail if the caller is a contract in which the asset is stored
+ assertApproxEqAbs(newReceiverShare, oldReceiverShare + shares, _delta_, "share");
+ if (oldAllowance != type(uint).max) assertApproxEqAbs(newAllowance, oldAllowance - assets, _delta_, "allowance");
+ }
+
+ //
+ // mint
+ //
+
+ // maxMint
+ // "MUST NOT revert."
+ function prop_maxMint(address caller, address receiver) public {
+ vm.prank(caller); IERC4626(_vault_).maxMint(receiver);
+ }
+
+ // previewMint
+ // "MUST return as close to and no fewer than the exact amount of assets
+ // that would be deposited in a mint call in the same transaction. I.e. mint
+ // should return the same or fewer assets as previewMint if called in the
+ // same transaction."
+ function prop_previewMint(address caller, address receiver, address other, uint shares) public {
+ vm.prank(other); uint assetsPreview = vault_previewMint(shares);
+ vm.prank(caller); uint assetsActual = vault_mint(shares, receiver);
+ assertApproxLeAbs(assetsActual, assetsPreview, _delta_);
+ }
+
+ // mint
+ function prop_mint(address caller, address receiver, uint shares) public {
+ uint oldCallerAsset = IERC20(_underlying_).balanceOf(caller);
+ uint oldReceiverShare = IERC20(_vault_).balanceOf(receiver);
+ uint oldAllowance = IERC20(_underlying_).allowance(caller, _vault_);
+
+ vm.prank(caller); uint assets = vault_mint(shares, receiver);
+
+ uint newCallerAsset = IERC20(_underlying_).balanceOf(caller);
+ uint newReceiverShare = IERC20(_vault_).balanceOf(receiver);
+ uint newAllowance = IERC20(_underlying_).allowance(caller, _vault_);
+
+ assertApproxEqAbs(newCallerAsset, oldCallerAsset - assets, _delta_, "asset"); // NOTE: this may fail if the caller is a contract in which the asset is stored
+ assertApproxEqAbs(newReceiverShare, oldReceiverShare + shares, _delta_, "share");
+ if (oldAllowance != type(uint).max) assertApproxEqAbs(newAllowance, oldAllowance - assets, _delta_, "allowance");
+ }
+
+ //
+ // withdraw
+ //
+
+ // maxWithdraw
+ // "MUST NOT revert."
+ // NOTE: some implementations failed due to arithmetic overflow
+ function prop_maxWithdraw(address caller, address owner) public {
+ vm.prank(caller); IERC4626(_vault_).maxWithdraw(owner);
+ }
+
+ // previewWithdraw
+ // "MUST return as close to and no fewer than the exact amount of Vault
+ // shares that would be burned in a withdraw call in the same transaction.
+ // I.e. withdraw should return the same or fewer shares as previewWithdraw
+ // if called in the same transaction."
+ function prop_previewWithdraw(address caller, address receiver, address owner, address other, uint assets) public {
+ vm.prank(other); uint preview = vault_previewWithdraw(assets);
+ vm.prank(caller); uint actual = vault_withdraw(assets, receiver, owner);
+ assertApproxLeAbs(actual, preview, _delta_);
+ }
+
+ // withdraw
+ function prop_withdraw(address caller, address receiver, address owner, uint assets) public {
+ uint oldReceiverAsset = IERC20(_underlying_).balanceOf(receiver);
+ uint oldOwnerShare = IERC20(_vault_).balanceOf(owner);
+ uint oldAllowance = IERC20(_vault_).allowance(owner, caller);
+
+ vm.prank(caller); uint shares = vault_withdraw(assets, receiver, owner);
+
+ uint newReceiverAsset = IERC20(_underlying_).balanceOf(receiver);
+ uint newOwnerShare = IERC20(_vault_).balanceOf(owner);
+ uint newAllowance = IERC20(_vault_).allowance(owner, caller);
+
+ assertApproxEqAbs(newOwnerShare, oldOwnerShare - shares, _delta_, "share");
+ assertApproxEqAbs(newReceiverAsset, oldReceiverAsset + assets, _delta_, "asset"); // NOTE: this may fail if the receiver is a contract in which the asset is stored
+ if (caller != owner && oldAllowance != type(uint).max) assertApproxEqAbs(newAllowance, oldAllowance - shares, _delta_, "allowance");
+
+ assertTrue(caller == owner || oldAllowance != 0 || (shares == 0 && assets == 0), "access control");
+ }
+
+ //
+ // redeem
+ //
+
+ // maxRedeem
+ // "MUST NOT revert."
+ function prop_maxRedeem(address caller, address owner) public {
+ vm.prank(caller); IERC4626(_vault_).maxRedeem(owner);
+ }
+
+ // previewRedeem
+ // "MUST return as close to and no more than the exact amount of assets that
+ // would be withdrawn in a redeem call in the same transaction. I.e. redeem
+ // should return the same or more assets as previewRedeem if called in the
+ // same transaction."
+ function prop_previewRedeem(address caller, address receiver, address owner, address other, uint shares) public {
+ vm.prank(other); uint preview = vault_previewRedeem(shares);
+ vm.prank(caller); uint actual = vault_redeem(shares, receiver, owner);
+ assertApproxGeAbs(actual, preview, _delta_);
+ }
+
+ // redeem
+ function prop_redeem(address caller, address receiver, address owner, uint shares) public {
+ uint oldReceiverAsset = IERC20(_underlying_).balanceOf(receiver);
+ uint oldOwnerShare = IERC20(_vault_).balanceOf(owner);
+ uint oldAllowance = IERC20(_vault_).allowance(owner, caller);
+
+ vm.prank(caller); uint assets = vault_redeem(shares, receiver, owner);
+
+ uint newReceiverAsset = IERC20(_underlying_).balanceOf(receiver);
+ uint newOwnerShare = IERC20(_vault_).balanceOf(owner);
+ uint newAllowance = IERC20(_vault_).allowance(owner, caller);
+
+ assertApproxEqAbs(newOwnerShare, oldOwnerShare - shares, _delta_, "share");
+ assertApproxEqAbs(newReceiverAsset, oldReceiverAsset + assets, _delta_, "asset"); // NOTE: this may fail if the receiver is a contract in which the asset is stored
+ if (caller != owner && oldAllowance != type(uint).max) assertApproxEqAbs(newAllowance, oldAllowance - shares, _delta_, "allowance");
+
+ assertTrue(caller == owner || oldAllowance != 0 || (shares == 0 && assets == 0), "access control");
+ }
+
+ //
+ // round trip properties
+ //
+
+ // redeem(deposit(a)) <= a
+ function prop_RT_deposit_redeem(address caller, uint assets) public {
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint shares = vault_deposit(assets, caller);
+ vm.prank(caller); uint assets2 = vault_redeem(shares, caller, caller);
+ assertApproxLeAbs(assets2, assets, _delta_);
+ }
+
+ // s = deposit(a)
+ // s' = withdraw(a)
+ // s' >= s
+ function prop_RT_deposit_withdraw(address caller, uint assets) public {
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint shares1 = vault_deposit(assets, caller);
+ vm.prank(caller); uint shares2 = vault_withdraw(assets, caller, caller);
+ assertApproxGeAbs(shares2, shares1, _delta_);
+ }
+
+ // deposit(redeem(s)) <= s
+ function prop_RT_redeem_deposit(address caller, uint shares) public {
+ vm.prank(caller); uint assets = vault_redeem(shares, caller, caller);
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint shares2 = vault_deposit(assets, caller);
+ assertApproxLeAbs(shares2, shares, _delta_);
+ }
+
+ // a = redeem(s)
+ // a' = mint(s)
+ // a' >= a
+ function prop_RT_redeem_mint(address caller, uint shares) public {
+ vm.prank(caller); uint assets1 = vault_redeem(shares, caller, caller);
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint assets2 = vault_mint(shares, caller);
+ assertApproxGeAbs(assets2, assets1, _delta_);
+ }
+
+ // withdraw(mint(s)) >= s
+ function prop_RT_mint_withdraw(address caller, uint shares) public {
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint assets = vault_mint(shares, caller);
+ vm.prank(caller); uint shares2 = vault_withdraw(assets, caller, caller);
+ assertApproxGeAbs(shares2, shares, _delta_);
+ }
+
+ // a = mint(s)
+ // a' = redeem(s)
+ // a' <= a
+ function prop_RT_mint_redeem(address caller, uint shares) public {
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint assets1 = vault_mint(shares, caller);
+ vm.prank(caller); uint assets2 = vault_redeem(shares, caller, caller);
+ assertApproxLeAbs(assets2, assets1, _delta_);
+ }
+
+ // mint(withdraw(a)) >= a
+ function prop_RT_withdraw_mint(address caller, uint assets) public {
+ vm.prank(caller); uint shares = vault_withdraw(assets, caller, caller);
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint assets2 = vault_mint(shares, caller);
+ assertApproxGeAbs(assets2, assets, _delta_);
+ }
+
+ // s = withdraw(a)
+ // s' = deposit(a)
+ // s' <= s
+ function prop_RT_withdraw_deposit(address caller, uint assets) public {
+ vm.prank(caller); uint shares1 = vault_withdraw(assets, caller, caller);
+ if (!_vaultMayBeEmpty) vm.assume(IERC20(_vault_).totalSupply() > 0);
+ vm.prank(caller); uint shares2 = vault_deposit(assets, caller);
+ assertApproxLeAbs(shares2, shares1, _delta_);
+ }
+
+ //
+ // utils
+ //
+
+ function vault_convertToShares(uint assets) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.convertToShares.selector, assets));
+ }
+ function vault_convertToAssets(uint shares) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.convertToAssets.selector, shares));
+ }
+
+ function vault_maxDeposit(address receiver) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.maxDeposit.selector, receiver));
+ }
+ function vault_maxMint(address receiver) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.maxMint.selector, receiver));
+ }
+ function vault_maxWithdraw(address owner) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.maxWithdraw.selector, owner));
+ }
+ function vault_maxRedeem(address owner) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.maxRedeem.selector, owner));
+ }
+
+ function vault_previewDeposit(uint assets) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.previewDeposit.selector, assets));
+ }
+ function vault_previewMint(uint shares) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.previewMint.selector, shares));
+ }
+ function vault_previewWithdraw(uint assets) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.previewWithdraw.selector, assets));
+ }
+ function vault_previewRedeem(uint shares) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.previewRedeem.selector, shares));
+ }
+
+ function vault_deposit(uint assets, address receiver) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.deposit.selector, assets, receiver));
+ }
+ function vault_mint(uint shares, address receiver) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.mint.selector, shares, receiver));
+ }
+ function vault_withdraw(uint assets, address receiver, address owner) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.withdraw.selector, assets, receiver, owner));
+ }
+ function vault_redeem(uint shares, address receiver, address owner) internal returns (uint) {
+ return _call_vault(abi.encodeWithSelector(IERC4626.redeem.selector, shares, receiver, owner));
+ }
+
+ function _call_vault(bytes memory data) internal returns (uint) {
+ (bool success, bytes memory retdata) = _vault_.call(data);
+ if (success) return abi.decode(retdata, (uint));
+ vm.assume(false); // if reverted, discard the current fuzz inputs, and let the fuzzer to start a new fuzz run
+ return 0; // silence warning
+ }
+
+ function assertApproxGeAbs(uint a, uint b, uint maxDelta) internal {
+ if (!(a >= b)) {
+ uint dt = b - a;
+ if (dt > maxDelta) {
+ emit log ("Error: a >=~ b not satisfied [uint]");
+ emit log_named_uint (" Value a", a);
+ emit log_named_uint (" Value b", b);
+ emit log_named_uint (" Max Delta", maxDelta);
+ emit log_named_uint (" Delta", dt);
+ fail();
+ }
+ }
+ }
+
+ function assertApproxLeAbs(uint a, uint b, uint maxDelta) internal {
+ if (!(a <= b)) {
+ uint dt = a - b;
+ if (dt > maxDelta) {
+ emit log ("Error: a <=~ b not satisfied [uint]");
+ emit log_named_uint (" Value a", a);
+ emit log_named_uint (" Value b", b);
+ emit log_named_uint (" Max Delta", maxDelta);
+ emit log_named_uint (" Delta", dt);
+ fail();
+ }
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/ERC4626.test.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/ERC4626.test.sol
new file mode 100644
index 000000000..6254a0547
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/ERC4626.test.sol
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: AGPL-3.0
+pragma solidity >=0.8.0 <0.9.0;
+
+import "./ERC4626.prop.sol";
+
+interface IMockERC20 is IERC20 {
+ function mint(address to, uint value) external;
+ function burn(address from, uint value) external;
+}
+
+abstract contract ERC4626Test is ERC4626Prop {
+ function setUp() public virtual;
+
+ uint constant N = 4;
+
+ struct Init {
+ address[N] user;
+ uint[N] share;
+ uint[N] asset;
+ int yield;
+ }
+
+ // setup initial vault state as follows:
+ //
+ // totalAssets == sum(init.share) + init.yield
+ // totalShares == sum(init.share)
+ //
+ // init.user[i]'s assets == init.asset[i]
+ // init.user[i]'s shares == init.share[i]
+ function setUpVault(Init memory init) public virtual {
+ // setup initial shares and assets for individual users
+ for (uint i = 0; i < N; i++) {
+ address user = init.user[i];
+ vm.assume(_isEOA(user));
+ // shares
+ uint shares = init.share[i];
+ try IMockERC20(_underlying_).mint(user, shares) {} catch { vm.assume(false); }
+ _approve(_underlying_, user, _vault_, shares);
+ vm.prank(user); try IERC4626(_vault_).deposit(shares, user) {} catch { vm.assume(false); }
+ // assets
+ uint assets = init.asset[i];
+ try IMockERC20(_underlying_).mint(user, assets) {} catch { vm.assume(false); }
+ }
+
+ // setup initial yield for vault
+ setUpYield(init);
+ }
+
+ // setup initial yield
+ function setUpYield(Init memory init) public virtual {
+ if (init.yield >= 0) { // gain
+ uint gain = uint(init.yield);
+ try IMockERC20(_underlying_).mint(_vault_, gain) {} catch { vm.assume(false); } // this can be replaced by calling yield generating functions if provided by the vault
+ } else { // loss
+ vm.assume(init.yield > type(int).min); // avoid overflow in conversion
+ uint loss = uint(-1 * init.yield);
+ try IMockERC20(_underlying_).burn(_vault_, loss) {} catch { vm.assume(false); } // this can be replaced by calling yield generating functions if provided by the vault
+ }
+ }
+
+ //
+ // asset
+ //
+
+ function test_asset(Init memory init) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ prop_asset(caller);
+ }
+
+ function test_totalAssets(Init memory init) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ prop_totalAssets(caller);
+ }
+
+ //
+ // convert
+ //
+
+ function test_convertToShares(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller1 = init.user[0];
+ address caller2 = init.user[1];
+ prop_convertToShares(caller1, caller2, assets);
+ }
+
+ function test_convertToAssets(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller1 = init.user[0];
+ address caller2 = init.user[1];
+ prop_convertToAssets(caller1, caller2, shares);
+ }
+
+ //
+ // deposit
+ //
+
+ function test_maxDeposit(Init memory init) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ prop_maxDeposit(caller, receiver);
+ }
+
+ function test_previewDeposit(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address other = init.user[2];
+ assets = bound(assets, 0, _max_deposit(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_previewDeposit(caller, receiver, other, assets);
+ }
+
+ function test_deposit(Init memory init, uint assets, uint allowance) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ assets = bound(assets, 0, _max_deposit(caller));
+ _approve(_underlying_, caller, _vault_, allowance);
+ prop_deposit(caller, receiver, assets);
+ }
+
+ //
+ // mint
+ //
+
+ function test_maxMint(Init memory init) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ prop_maxMint(caller, receiver);
+ }
+
+ function test_previewMint(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address other = init.user[2];
+ shares = bound(shares, 0, _max_mint(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_previewMint(caller, receiver, other, shares);
+ }
+
+ function test_mint(Init memory init, uint shares, uint allowance) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ shares = bound(shares, 0, _max_mint(caller));
+ _approve(_underlying_, caller, _vault_, allowance);
+ prop_mint(caller, receiver, shares);
+ }
+
+ //
+ // withdraw
+ //
+
+ function test_maxWithdraw(Init memory init) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address owner = init.user[1];
+ prop_maxWithdraw(caller, owner);
+ }
+
+ function test_previewWithdraw(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address owner = init.user[2];
+ address other = init.user[3];
+ assets = bound(assets, 0, _max_withdraw(owner));
+ _approve(_vault_, owner, caller, type(uint).max);
+ prop_previewWithdraw(caller, receiver, owner, other, assets);
+ }
+
+ function test_withdraw(Init memory init, uint assets, uint allowance) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address owner = init.user[2];
+ assets = bound(assets, 0, _max_withdraw(owner));
+ _approve(_vault_, owner, caller, allowance);
+ prop_withdraw(caller, receiver, owner, assets);
+ }
+
+ function testFail_withdraw(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address owner = init.user[2];
+ assets = bound(assets, 0, _max_withdraw(owner));
+ vm.assume(caller != owner);
+ vm.assume(assets > 0);
+ _approve(_vault_, owner, caller, 0);
+ vm.prank(caller); uint shares = IERC4626(_vault_).withdraw(assets, receiver, owner);
+ assertGt(shares, 0); // this assert is expected to fail
+ }
+
+ //
+ // redeem
+ //
+
+ function test_maxRedeem(Init memory init) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address owner = init.user[1];
+ prop_maxRedeem(caller, owner);
+ }
+
+ function test_previewRedeem(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address owner = init.user[2];
+ address other = init.user[3];
+ shares = bound(shares, 0, _max_redeem(owner));
+ _approve(_vault_, owner, caller, type(uint).max);
+ prop_previewRedeem(caller, receiver, owner, other, shares);
+ }
+
+ function test_redeem(Init memory init, uint shares, uint allowance) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address owner = init.user[2];
+ shares = bound(shares, 0, _max_redeem(owner));
+ _approve(_vault_, owner, caller, allowance);
+ prop_redeem(caller, receiver, owner, shares);
+ }
+
+ function testFail_redeem(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ address receiver = init.user[1];
+ address owner = init.user[2];
+ shares = bound(shares, 0, _max_redeem(owner));
+ vm.assume(caller != owner);
+ vm.assume(shares > 0);
+ _approve(_vault_, owner, caller, 0);
+ vm.prank(caller); IERC4626(_vault_).redeem(shares, receiver, owner);
+ }
+
+ //
+ // round trip tests
+ //
+
+ function test_RT_deposit_redeem(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ assets = bound(assets, 0, _max_deposit(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_deposit_redeem(caller, assets);
+ }
+
+ function test_RT_deposit_withdraw(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ assets = bound(assets, 0, _max_deposit(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_deposit_withdraw(caller, assets);
+ }
+
+ function test_RT_redeem_deposit(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ shares = bound(shares, 0, _max_redeem(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_redeem_deposit(caller, shares);
+ }
+
+ function test_RT_redeem_mint(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ shares = bound(shares, 0, _max_redeem(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_redeem_mint(caller, shares);
+ }
+
+ function test_RT_mint_withdraw(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ shares = bound(shares, 0, _max_mint(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_mint_withdraw(caller, shares);
+ }
+
+ function test_RT_mint_redeem(Init memory init, uint shares) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ shares = bound(shares, 0, _max_mint(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_mint_redeem(caller, shares);
+ }
+
+ function test_RT_withdraw_mint(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ assets = bound(assets, 0, _max_withdraw(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_withdraw_mint(caller, assets);
+ }
+
+ function test_RT_withdraw_deposit(Init memory init, uint assets) public virtual {
+ setUpVault(init);
+ address caller = init.user[0];
+ assets = bound(assets, 0, _max_withdraw(caller));
+ _approve(_underlying_, caller, _vault_, type(uint).max);
+ prop_RT_withdraw_deposit(caller, assets);
+ }
+
+ //
+ // utils
+ //
+
+ function _isContract(address account) internal view returns (bool) { return account.code.length > 0; }
+ function _isEOA (address account) internal view returns (bool) { return account.code.length == 0; }
+
+ function _approve(address token, address owner, address spender, uint amount) internal {
+ vm.prank(owner); _safeApprove(token, spender, 0);
+ vm.prank(owner); _safeApprove(token, spender, amount);
+ }
+
+ function _safeApprove(address token, address spender, uint amount) internal {
+ (bool success, bytes memory retdata) = token.call(abi.encodeWithSelector(IERC20.approve.selector, spender, amount));
+ vm.assume(success);
+ if (retdata.length > 0) vm.assume(abi.decode(retdata, (bool)));
+ }
+
+ function _max_deposit(address from) internal virtual returns (uint) {
+ if (_unlimitedAmount) return type(uint).max;
+ return IERC20(_underlying_).balanceOf(from);
+ }
+
+ function _max_mint(address from) internal virtual returns (uint) {
+ if (_unlimitedAmount) return type(uint).max;
+ return vault_convertToShares(IERC20(_underlying_).balanceOf(from));
+ }
+
+ function _max_withdraw(address from) internal virtual returns (uint) {
+ if (_unlimitedAmount) return type(uint).max;
+ return vault_convertToAssets(IERC20(_vault_).balanceOf(from)); // may be different from maxWithdraw(from)
+ }
+
+ function _max_redeem(address from) internal virtual returns (uint) {
+ if (_unlimitedAmount) return type(uint).max;
+ return IERC20(_vault_).balanceOf(from); // may be different from maxRedeem(from)
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/LICENSE b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/LICENSE
new file mode 100644
index 000000000..0ad25db4b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/LICENSE
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+ .
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/README.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/README.md
new file mode 100644
index 000000000..c4731fc67
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/erc4626-tests/README.md
@@ -0,0 +1,121 @@
+# ERC4626 Property Tests
+
+Foundry (dapptools-style) property-based tests for [ERC4626] standard conformance.
+
+[ERC4626]: https://eips.ethereum.org/EIPS/eip-4626
+
+You can read our post on "_[Generalized property tests for ERC4626 vaults][post]_."
+
+[post]: https://a16zcrypto.com/generalized-property-tests-for-erc4626-vaults
+
+## Overview
+
+#### What is it?
+
+- Test suites for checking if the given ERC4626 implementation satisfies the **standard requirements**.
+- Dapptools-style **property-based tests** for fuzzing or symbolic execution testing.
+- Tests that are **independent** from implementation details, thus applicable for any ERC4626 vaults.
+
+#### What isn’t it?
+
+- It does NOT test implementation-specific details, e.g., how to generate and distribute yields, how to compute the share price, etc.
+
+#### Testing properties:
+
+- **Round-trip properties**: no one can make a free profit by depositing and immediately withdrawing back and forth.
+
+- **Functional correctness**: the `deposit()`, `mint()`, `withdraw()`, and `redeem()` functions update the balance and allowance properly.
+
+- The `preview{Deposit,Redeem}()` functions **MUST NOT over-estimate** the exact amount.[^1]
+
+[^1]: That is, the `deposit()` and `redeem()` functions “MUST return the same or more amounts as their preview function if called in the same transaction.”
+
+- The `preview{Mint,Withdraw}()` functions **MUST NOT under-estimate** the exact amount.[^2]
+
+[^2]: That is, the `mint()` and `withdraw()` functions “MUST return the same or fewer amounts as their preview function if called in the same transaction.”
+
+- The `convertTo{Shares,Assets}` functions “**MUST NOT show any variations** depending on the caller.”
+
+- The `asset()`, `totalAssets()`, and `max{Deposit,Mint,Withdraw,Redeem}()` functions “**MUST NOT revert**.”
+
+## Usage
+
+**Step 0**: Install [foundry] and add [forge-std] in your vault repo:
+
+```bash
+$ curl -L https://foundry.paradigm.xyz | bash
+
+$ cd /path/to/your-erc4626-vault
+$ forge install foundry-rs/forge-std
+```
+
+[foundry]: https://getfoundry.sh/
+[forge-std]: https://github.com/foundry-rs/forge-std
+
+**Step 1**: Add this [erc4626-tests] as a dependency to your vault:
+
+```bash
+$ cd /path/to/your-erc4626-vault
+$ forge install a16z/erc4626-tests
+```
+
+[erc4626-tests]: https://github.com/a16z/erc4626-tests
+
+**Step 2**: Extend the abstract test contract [`ERC4626Test`](ERC4626.test.sol) with your own custom vault setup method, for example:
+
+```solidity
+// SPDX-License-Identifier: AGPL-3.0
+pragma solidity >=0.8.0 <0.9.0;
+
+import 'erc4626-tests/ERC4626.test.sol';
+
+import { ERC20Mock } from '/path/to/mocks/ERC20Mock.sol';
+import { ERC4626Mock } from '/path/to/mocks/ERC4626Mock.sol';
+
+contract ERC4626StdTest is ERC4626Test {
+ function setUp() public override {
+ _underlying_ = address(new ERC20Mock('Mock ERC20', 'MERC20', 18));
+ _vault_ = address(new ERC4626Mock(ERC20Mock(__underlying__), 'Mock ERC4626', 'MERC4626'));
+ _delta_ = 0;
+ _vaultMayBeEmpty = false;
+ _unlimitedAmount = false;
+ }
+}
+```
+
+Specifically, set the state variables as follows:
+
+- `_vault_`: the address of your ERC4626 vault.
+- `_underlying_`: the address of the underlying asset of your vault. Note that the default `setupVault()` and `setupYield()` methods of `ERC4626Test` assume that it implements `mint(address to, uint value)` and `burn(address from, uint value)`. You can override the setup methods with your own if such `mint()` and `burn()` are not implemented.
+- `_delta_`: the maximum approximation error size to be passed to [`assertApproxEqAbs()`]. It must be given as an absolute value (not a percentage) in the smallest unit (e.g., Wei or Satoshi). Note that all the tests are expected to pass with `__delta__ == 0` as long as your vault follows the [preferred rounding direction] as specified in the standard. If your vault doesn't follow the preferred rounding direction, you can set `__delta__` to a reasonable size of rounding errors where the adversarial profit of exploiting such rounding errors stays sufficiently small compared to the gas cost. (You can read our [post] for more about the adversarial profit.)
+- `_vaultMayBeEmpty`: when set to false, fuzz inputs that empties the vault are ignored.
+- `_unlimitedAmount`: when set to false, fuzz inputs are restricted to the currently available amount from the caller. Limiting the amount can speed up fuzzing, but may miss some edge cases.
+
+[`assertApproxEqAbs()`]: https://book.getfoundry.sh/reference/forge-std/assertApproxEqAbs
+[preferred rounding direction]: https://eips.ethereum.org/EIPS/eip-4626#security-considerations
+
+**Step 3**: Run `forge test`
+
+```
+$ forge test
+```
+
+## Examples
+
+Below are examples of adding these property tests to existing ERC4626 vaults:
+
+- [OpenZeppelin ERC4626] [[diff](https://github.com/daejunpark/openzeppelin-contracts/pull/1/files)]
+- [Solmate ERC4626] [[diff](https://github.com/daejunpark/solmate/pull/1/files)]
+- [Revenue Distribution Token] [[diff](https://github.com/daejunpark/revenue-distribution-token/pull/1/files)]
+- [Yield Daddy ERC4626 wrappers] [[diff](https://github.com/daejunpark/yield-daddy/pull/1/files)][^bug]
+
+[OpenZeppelin ERC4626]: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a1948250ab8c441f6d327a65754cb20d2b1b4554/contracts/token/ERC20/extensions/ERC4626.sol
+[Solmate ERC4626]: https://github.com/transmissions11/solmate/blob/c2594bf4635ad773a8f4763e20b7e79582e41535/src/mixins/ERC4626.sol
+[Revenue Distribution Token]: https://github.com/maple-labs/revenue-distribution-token/blob/be9592fd72bfa7142a217507f2d5500a7856329e/contracts/RevenueDistributionToken.sol
+[Yield Daddy ERC4626 wrappers]: https://github.com/timeless-fi/yield-daddy
+
+[^bug]: Our property tests indeed revealed an [issue](https://github.com/timeless-fi/yield-daddy/issues/7) in their eToken testing mock contract. The tests passed after it is [fixed](https://github.com/daejunpark/yield-daddy/commit/721cf4bd766805fd409455434aa5fd1a9b2df25c).
+
+## Disclaimer
+
+_These smart contracts are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions or loss of transmitted information. THE SMART CONTRACTS CONTAINED HEREIN ARE FURNISHED AS IS, WHERE IS, WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, NON-INFRINGEMENT OR FITNESS FOR ANY PARTICULAR PURPOSE. Further, use of any of these smart contracts may be restricted or prohibited under applicable law, including securities laws, and it is therefore strongly advised for you to contact a reputable attorney in any jurisdiction where these smart contracts may be accessible for any questions or concerns with respect thereto. Further, no information provided in this repo should be construed as investment advice or legal advice for any particular facts or circumstances, and is not meant to replace competent counsel. a16z is not liable for any use of the foregoing, and users should proceed with caution and use at their own risk. See a16z.com/disclosures for more info._
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.gitattributes b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.gitattributes
new file mode 100644
index 000000000..27042d458
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.gitattributes
@@ -0,0 +1 @@
+src/Vm.sol linguist-generated
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/ci.yml b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/ci.yml
new file mode 100644
index 000000000..2d68e91fb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/ci.yml
@@ -0,0 +1,128 @@
+name: CI
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - master
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Print forge version
+ run: forge --version
+
+ # Backwards compatibility checks:
+ # - the oldest and newest version of each supported minor version
+ # - versions with specific issues
+ - name: Check compatibility with latest
+ if: always()
+ run: |
+ output=$(forge build --skip test)
+ if echo "$output" | grep -q "Warning"; then
+ echo "$output"
+ exit 1
+ fi
+
+ - name: Check compatibility with 0.8.0
+ if: always()
+ run: |
+ output=$(forge build --skip test --use solc:0.8.0)
+ if echo "$output" | grep -q "Warning"; then
+ echo "$output"
+ exit 1
+ fi
+
+ - name: Check compatibility with 0.7.6
+ if: always()
+ run: |
+ output=$(forge build --skip test --use solc:0.7.6)
+ if echo "$output" | grep -q "Warning"; then
+ echo "$output"
+ exit 1
+ fi
+
+ - name: Check compatibility with 0.7.0
+ if: always()
+ run: |
+ output=$(forge build --skip test --use solc:0.7.0)
+ if echo "$output" | grep -q "Warning"; then
+ echo "$output"
+ exit 1
+ fi
+
+ - name: Check compatibility with 0.6.12
+ if: always()
+ run: |
+ output=$(forge build --skip test --use solc:0.6.12)
+ if echo "$output" | grep -q "Warning"; then
+ echo "$output"
+ exit 1
+ fi
+
+ - name: Check compatibility with 0.6.2
+ if: always()
+ run: |
+ output=$(forge build --skip test --use solc:0.6.2)
+ if echo "$output" | grep -q "Warning"; then
+ echo "$output"
+ exit 1
+ fi
+
+ # via-ir compilation time checks.
+ - name: Measure compilation time of Test with 0.8.17 --via-ir
+ if: always()
+ run: forge build --skip test --contracts test/compilation/CompilationTest.sol --use solc:0.8.17 --via-ir
+
+ - name: Measure compilation time of TestBase with 0.8.17 --via-ir
+ if: always()
+ run: forge build --skip test --contracts test/compilation/CompilationTestBase.sol --use solc:0.8.17 --via-ir
+
+ - name: Measure compilation time of Script with 0.8.17 --via-ir
+ if: always()
+ run: forge build --skip test --contracts test/compilation/CompilationScript.sol --use solc:0.8.17 --via-ir
+
+ - name: Measure compilation time of ScriptBase with 0.8.17 --via-ir
+ if: always()
+ run: forge build --skip test --contracts test/compilation/CompilationScriptBase.sol --use solc:0.8.17 --via-ir
+
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Print forge version
+ run: forge --version
+
+ - name: Run tests
+ run: forge test -vvv
+
+ fmt:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Print forge version
+ run: forge --version
+
+ - name: Check formatting
+ run: forge fmt --check
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/sync.yml b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/sync.yml
new file mode 100644
index 000000000..9b170f0b7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/.github/workflows/sync.yml
@@ -0,0 +1,31 @@
+name: Sync Release Branch
+
+on:
+ release:
+ types:
+ - created
+
+jobs:
+ sync-release-branch:
+ runs-on: ubuntu-latest
+ if: startsWith(github.event.release.tag_name, 'v1')
+ steps:
+ - name: Check out the repo
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: v1
+
+ # The email is derived from the bots user id,
+ # found here: https://api.github.com/users/github-actions%5Bbot%5D
+ - name: Configure Git
+ run: |
+ git config user.name github-actions[bot]
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
+
+ - name: Sync Release Branch
+ run: |
+ git fetch --tags
+ git checkout v1
+ git reset --hard ${GITHUB_REF}
+ git push --force
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/LICENSE-APACHE b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/LICENSE-APACHE
new file mode 100644
index 000000000..cf01a499f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/LICENSE-APACHE
@@ -0,0 +1,203 @@
+Copyright Contributors to Forge Standard Library
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/LICENSE-MIT b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/LICENSE-MIT
new file mode 100644
index 000000000..28f98304a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright Contributors to Forge Standard Library
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.R
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/README.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/README.md
new file mode 100644
index 000000000..230aaf263
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/README.md
@@ -0,0 +1,235 @@
+# Forge Standard Library • [](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml)
+
+Forge Standard Library is a collection of helpful contracts and libraries for use with [Forge and Foundry](https://github.com/foundry-rs/foundry). It leverages Forge's cheatcodes to make writing tests easier and faster, while improving the UX of cheatcodes.
+
+**Learn how to use Forge-Std with the [📖 Foundry Book (Forge-Std Guide)](https://book.getfoundry.sh/forge/forge-std.html).**
+
+## Install
+
+```bash
+forge install foundry-rs/forge-std
+```
+
+## Contracts
+
+### stdError
+
+This is a helper contract for errors and reverts. In Forge, this contract is particularly helpful for the `expectRevert` cheatcode, as it provides all compiler builtin errors.
+
+See the contract itself for all error codes.
+
+#### Example usage
+
+```solidity
+import 'forge-std/Test.sol';
+
+contract TestContract is Test {
+ ErrorsTest test;
+
+ function setUp() public {
+ test = new ErrorsTest();
+ }
+
+ function testExpectArithmetic() public {
+ vm.expectRevert(stdError.arithmeticError);
+ test.arithmeticError(10);
+ }
+}
+
+contract ErrorsTest {
+ function arithmeticError(uint256 a) public {
+ uint256 a = a - 100;
+ }
+}
+```
+
+### stdStorage
+
+This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can _always_ find and write the storage slot(s) associated with a particular variable without knowing the storage layout. The one _major_ caveat to this is while a slot can be found for packed storage variables, we can't write to that variable safely. If a user tries to write to a packed slot, the execution throws an error, unless it is uninitialized (`bytes32(0)`).
+
+This works by recording all `SLOAD`s and `SSTORE`s during a function call. If there is a single slot read or written to, it immediately returns the slot. Otherwise, behind the scenes, we iterate through and check each one (assuming the user passed in a `depth` parameter). If the variable is a struct, you can pass in a `depth` parameter which is basically the field depth.
+
+I.e.:
+
+```solidity
+struct T {
+ // depth 0
+ uint256 a;
+ // depth 1
+ uint256 b;
+}
+```
+
+#### Example usage
+
+```solidity
+import 'forge-std/Test.sol';
+
+contract TestContract is Test {
+ using stdStorage for StdStorage;
+
+ Storage test;
+
+ function setUp() public {
+ test = new Storage();
+ }
+
+ function testFindExists() public {
+ // Lets say we want to find the slot for the public
+ // variable `exists`. We just pass in the function selector
+ // to the `find` command
+ uint256 slot = stdstore.target(address(test)).sig('exists()').find();
+ assertEq(slot, 0);
+ }
+
+ function testWriteExists() public {
+ // Lets say we want to write to the slot for the public
+ // variable `exists`. We just pass in the function selector
+ // to the `checked_write` command
+ stdstore.target(address(test)).sig('exists()').checked_write(100);
+ assertEq(test.exists(), 100);
+ }
+
+ // It supports arbitrary storage layouts, like assembly based storage locations
+ function testFindHidden() public {
+ // `hidden` is a random hash of a bytes, iteration through slots would
+ // not find it. Our mechanism does
+ // Also, you can use the selector instead of a string
+ uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find();
+ assertEq(slot, uint256(keccak256('my.random.var')));
+ }
+
+ // If targeting a mapping, you have to pass in the keys necessary to perform the find
+ // i.e.:
+ function testFindMapping() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).find();
+ // in the `Storage` constructor, we wrote that this address' value was 1 in the map
+ // so when we load the slot, we expect it to be 1
+ assertEq(uint(vm.load(address(test), bytes32(slot))), 1);
+ }
+
+ // If the target is a struct, you can specify the field depth:
+ function testFindStruct() public {
+ // NOTE: see the depth parameter - 0 means 0th field, 1 means 1st field, etc.
+ uint256 slot_for_a_field = stdstore.target(address(test)).sig(test.basicStruct.selector).depth(0).find();
+
+ uint256 slot_for_b_field = stdstore.target(address(test)).sig(test.basicStruct.selector).depth(1).find();
+
+ assertEq(uint(vm.load(address(test), bytes32(slot_for_a_field))), 1);
+ assertEq(uint(vm.load(address(test), bytes32(slot_for_b_field))), 2);
+ }
+}
+
+// A complex storage contract
+contract Storage {
+ struct UnpackedStruct {
+ uint256 a;
+ uint256 b;
+ }
+
+ constructor() {
+ map_addr[msg.sender] = 1;
+ }
+
+ uint256 public exists = 1;
+ mapping(address => uint256) public map_addr;
+ // mapping(address => Packed) public map_packed;
+ mapping(address => UnpackedStruct) public map_struct;
+ mapping(address => mapping(address => uint256)) public deep_map;
+ mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
+ UnpackedStruct public basicStruct = UnpackedStruct({ a: 1, b: 2 });
+
+ function hidden() public view returns (bytes32 t) {
+ // an extremely hidden storage slot
+ bytes32 slot = keccak256('my.random.var');
+ assembly {
+ t := sload(slot)
+ }
+ }
+}
+```
+
+### stdCheats
+
+This is a wrapper over miscellaneous cheatcodes that need wrappers to be more dev friendly. Currently there are only functions related to `prank`. In general, users may expect ETH to be put into an address on `prank`, but this is not the case for safety reasons. Explicitly this `hoax` function should only be used for addresses that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you.
+
+#### Example usage:
+
+```solidity
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import 'forge-std/Test.sol';
+
+// Inherit the stdCheats
+contract StdCheatsTest is Test {
+ Bar test;
+ function setUp() public {
+ test = new Bar();
+ }
+
+ function testHoax() public {
+ // we call `hoax`, which gives the target address
+ // eth and then calls `prank`
+ hoax(address(1337));
+ test.bar{ value: 100 }(address(1337));
+
+ // overloaded to allow you to specify how much eth to
+ // initialize the address with
+ hoax(address(1337), 1);
+ test.bar{ value: 1 }(address(1337));
+ }
+
+ function testStartHoax() public {
+ // we call `startHoax`, which gives the target address
+ // eth and then calls `startPrank`
+ //
+ // it is also overloaded so that you can specify an eth amount
+ startHoax(address(1337));
+ test.bar{ value: 100 }(address(1337));
+ test.bar{ value: 100 }(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+}
+
+contract Bar {
+ function bar(address expectedSender) public payable {
+ require(msg.sender == expectedSender, '!prank');
+ }
+}
+```
+
+### Std Assertions
+
+Contains various assertions.
+
+### `console.log`
+
+Usage follows the same format as [Hardhat](https://hardhat.org/hardhat-network/reference/#console-log).
+It's recommended to use `console2.sol` as shown below, as this will show the decoded logs in Forge traces.
+
+```solidity
+// import it indirectly via Test.sol
+import "forge-std/Test.sol";
+// or directly import it
+import "forge-std/console2.sol";
+...
+console2.log(someValue);
+```
+
+If you need compatibility with Hardhat, you must use the standard `console.sol` instead.
+Due to a bug in `console.sol`, logs that use `uint256` or `int256` types will not be properly decoded in Forge traces.
+
+```solidity
+// import it indirectly via Test.sol
+import "forge-std/Test.sol";
+// or directly import it
+import "forge-std/console.sol";
+...
+console.log(someValue);
+```
+
+## License
+
+Forge Standard Library is offered under either [MIT](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE) license.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/foundry.toml b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/foundry.toml
new file mode 100644
index 000000000..2bc66fa77
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/foundry.toml
@@ -0,0 +1,21 @@
+[profile.default]
+fs_permissions = [{ access = "read-write", path = "./"}]
+
+[rpc_endpoints]
+# The RPC URLs are modified versions of the default for testing initialization.
+mainnet = "https://eth-mainnet.alchemyapi.io/v2/WV407BEiBmjNJfKo9Uo_55u0z0ITyCOX" # Different API key.
+optimism_sepolia = "https://sepolia.optimism.io/" # Adds a trailing slash.
+arbitrum_one_sepolia = "https://sepolia-rollup.arbitrum.io/rpc/" # Adds a trailing slash.
+needs_undefined_env_var = "${UNDEFINED_RPC_URL_PLACEHOLDER}"
+
+[fmt]
+# These are all the `forge fmt` defaults.
+line_length = 120
+tab_width = 4
+bracket_spacing = false
+int_types = 'long'
+multiline_func_header = 'attributes_first'
+quote_style = 'double'
+number_underscore = 'preserve'
+single_line_statement_blocks = 'preserve'
+ignore = ["src/console.sol", "src/console2.sol"]
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/package.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/package.json
new file mode 100644
index 000000000..9bc3d242c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "forge-std",
+ "version": "1.9.3",
+ "description": "Forge Standard Library is a collection of helpful contracts and libraries for use with Forge and Foundry.",
+ "homepage": "https://book.getfoundry.sh/forge/forge-std",
+ "bugs": "https://github.com/foundry-rs/forge-std/issues",
+ "license": "(Apache-2.0 OR MIT)",
+ "author": "Contributors to Forge Standard Library",
+ "files": [
+ "src/**/*"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/foundry-rs/forge-std.git"
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/scripts/vm.py b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/scripts/vm.py
new file mode 100644
index 000000000..f0537db9b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/scripts/vm.py
@@ -0,0 +1,635 @@
+#!/usr/bin/env python3
+
+import copy
+import json
+import re
+import subprocess
+from enum import Enum as PyEnum
+from typing import Callable
+from urllib import request
+
+VoidFn = Callable[[], None]
+
+CHEATCODES_JSON_URL = "https://raw.githubusercontent.com/foundry-rs/foundry/master/crates/cheatcodes/assets/cheatcodes.json"
+OUT_PATH = "src/Vm.sol"
+
+VM_SAFE_DOC = """\
+/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
+/// result in Script simulations differing from on-chain execution. It is recommended to only use
+/// these cheats in scripts.
+"""
+
+VM_DOC = """\
+/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
+/// in tests, but it is not recommended to use these cheats in scripts.
+"""
+
+
+def main():
+ json_str = request.urlopen(CHEATCODES_JSON_URL).read().decode("utf-8")
+ contract = Cheatcodes.from_json(json_str)
+
+ ccs = contract.cheatcodes
+ ccs = list(filter(lambda cc: cc.status not in ["experimental", "internal"], ccs))
+ ccs.sort(key=lambda cc: cc.func.id)
+
+ safe = list(filter(lambda cc: cc.safety == "safe", ccs))
+ safe.sort(key=CmpCheatcode)
+ unsafe = list(filter(lambda cc: cc.safety == "unsafe", ccs))
+ unsafe.sort(key=CmpCheatcode)
+ assert len(safe) + len(unsafe) == len(ccs)
+
+ prefix_with_group_headers(safe)
+ prefix_with_group_headers(unsafe)
+
+ out = ""
+
+ out += "// Automatically @generated by scripts/vm.py. Do not modify manually.\n\n"
+
+ pp = CheatcodesPrinter(
+ spdx_identifier="MIT OR Apache-2.0",
+ solidity_requirement=">=0.6.2 <0.9.0",
+ abicoder_pragma=True,
+ )
+ pp.p_prelude()
+ pp.prelude = False
+ out += pp.finish()
+
+ out += "\n\n"
+ out += VM_SAFE_DOC
+ vm_safe = Cheatcodes(
+ # TODO: Custom errors were introduced in 0.8.4
+ errors=[], # contract.errors
+ events=contract.events,
+ enums=contract.enums,
+ structs=contract.structs,
+ cheatcodes=safe,
+ )
+ pp.p_contract(vm_safe, "VmSafe")
+ out += pp.finish()
+
+ out += "\n\n"
+ out += VM_DOC
+ vm_unsafe = Cheatcodes(
+ errors=[],
+ events=[],
+ enums=[],
+ structs=[],
+ cheatcodes=unsafe,
+ )
+ pp.p_contract(vm_unsafe, "Vm", "VmSafe")
+ out += pp.finish()
+
+ # Compatibility with <0.8.0
+ def memory_to_calldata(m: re.Match) -> str:
+ return " calldata " + m.group(1)
+
+ out = re.sub(r" memory (.*returns)", memory_to_calldata, out)
+
+ with open(OUT_PATH, "w") as f:
+ f.write(out)
+
+ forge_fmt = ["forge", "fmt", OUT_PATH]
+ res = subprocess.run(forge_fmt)
+ assert res.returncode == 0, f"command failed: {forge_fmt}"
+
+ print(f"Wrote to {OUT_PATH}")
+
+
+class CmpCheatcode:
+ cheatcode: "Cheatcode"
+
+ def __init__(self, cheatcode: "Cheatcode"):
+ self.cheatcode = cheatcode
+
+ def __lt__(self, other: "CmpCheatcode") -> bool:
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) < 0
+
+ def __eq__(self, other: "CmpCheatcode") -> bool:
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) == 0
+
+ def __gt__(self, other: "CmpCheatcode") -> bool:
+ return cmp_cheatcode(self.cheatcode, other.cheatcode) > 0
+
+
+def cmp_cheatcode(a: "Cheatcode", b: "Cheatcode") -> int:
+ if a.group != b.group:
+ return -1 if a.group < b.group else 1
+ if a.status != b.status:
+ return -1 if a.status < b.status else 1
+ if a.safety != b.safety:
+ return -1 if a.safety < b.safety else 1
+ if a.func.id != b.func.id:
+ return -1 if a.func.id < b.func.id else 1
+ return 0
+
+
+# HACK: A way to add group header comments without having to modify printer code
+def prefix_with_group_headers(cheats: list["Cheatcode"]):
+ s = set()
+ for i, cheat in enumerate(cheats):
+ if cheat.group in s:
+ continue
+
+ s.add(cheat.group)
+
+ c = copy.deepcopy(cheat)
+ c.func.description = ""
+ c.func.declaration = f"// ======== {group(c.group)} ========"
+ cheats.insert(i, c)
+ return cheats
+
+
+def group(s: str) -> str:
+ if s == "evm":
+ return "EVM"
+ if s == "json":
+ return "JSON"
+ return s[0].upper() + s[1:]
+
+
+class Visibility(PyEnum):
+ EXTERNAL: str = "external"
+ PUBLIC: str = "public"
+ INTERNAL: str = "internal"
+ PRIVATE: str = "private"
+
+ def __str__(self):
+ return self.value
+
+
+class Mutability(PyEnum):
+ PURE: str = "pure"
+ VIEW: str = "view"
+ NONE: str = ""
+
+ def __str__(self):
+ return self.value
+
+
+class Function:
+ id: str
+ description: str
+ declaration: str
+ visibility: Visibility
+ mutability: Mutability
+ signature: str
+ selector: str
+ selector_bytes: bytes
+
+ def __init__(
+ self,
+ id: str,
+ description: str,
+ declaration: str,
+ visibility: Visibility,
+ mutability: Mutability,
+ signature: str,
+ selector: str,
+ selector_bytes: bytes,
+ ):
+ self.id = id
+ self.description = description
+ self.declaration = declaration
+ self.visibility = visibility
+ self.mutability = mutability
+ self.signature = signature
+ self.selector = selector
+ self.selector_bytes = selector_bytes
+
+ @staticmethod
+ def from_dict(d: dict) -> "Function":
+ return Function(
+ d["id"],
+ d["description"],
+ d["declaration"],
+ Visibility(d["visibility"]),
+ Mutability(d["mutability"]),
+ d["signature"],
+ d["selector"],
+ bytes(d["selectorBytes"]),
+ )
+
+
+class Cheatcode:
+ func: Function
+ group: str
+ status: str
+ safety: str
+
+ def __init__(self, func: Function, group: str, status: str, safety: str):
+ self.func = func
+ self.group = group
+ self.status = status
+ self.safety = safety
+
+ @staticmethod
+ def from_dict(d: dict) -> "Cheatcode":
+ return Cheatcode(
+ Function.from_dict(d["func"]),
+ str(d["group"]),
+ str(d["status"]),
+ str(d["safety"]),
+ )
+
+
+class Error:
+ name: str
+ description: str
+ declaration: str
+
+ def __init__(self, name: str, description: str, declaration: str):
+ self.name = name
+ self.description = description
+ self.declaration = declaration
+
+ @staticmethod
+ def from_dict(d: dict) -> "Error":
+ return Error(**d)
+
+
+class Event:
+ name: str
+ description: str
+ declaration: str
+
+ def __init__(self, name: str, description: str, declaration: str):
+ self.name = name
+ self.description = description
+ self.declaration = declaration
+
+ @staticmethod
+ def from_dict(d: dict) -> "Event":
+ return Event(**d)
+
+
+class EnumVariant:
+ name: str
+ description: str
+
+ def __init__(self, name: str, description: str):
+ self.name = name
+ self.description = description
+
+
+class Enum:
+ name: str
+ description: str
+ variants: list[EnumVariant]
+
+ def __init__(self, name: str, description: str, variants: list[EnumVariant]):
+ self.name = name
+ self.description = description
+ self.variants = variants
+
+ @staticmethod
+ def from_dict(d: dict) -> "Enum":
+ return Enum(
+ d["name"],
+ d["description"],
+ list(map(lambda v: EnumVariant(**v), d["variants"])),
+ )
+
+
+class StructField:
+ name: str
+ ty: str
+ description: str
+
+ def __init__(self, name: str, ty: str, description: str):
+ self.name = name
+ self.ty = ty
+ self.description = description
+
+
+class Struct:
+ name: str
+ description: str
+ fields: list[StructField]
+
+ def __init__(self, name: str, description: str, fields: list[StructField]):
+ self.name = name
+ self.description = description
+ self.fields = fields
+
+ @staticmethod
+ def from_dict(d: dict) -> "Struct":
+ return Struct(
+ d["name"],
+ d["description"],
+ list(map(lambda f: StructField(**f), d["fields"])),
+ )
+
+
+class Cheatcodes:
+ errors: list[Error]
+ events: list[Event]
+ enums: list[Enum]
+ structs: list[Struct]
+ cheatcodes: list[Cheatcode]
+
+ def __init__(
+ self,
+ errors: list[Error],
+ events: list[Event],
+ enums: list[Enum],
+ structs: list[Struct],
+ cheatcodes: list[Cheatcode],
+ ):
+ self.errors = errors
+ self.events = events
+ self.enums = enums
+ self.structs = structs
+ self.cheatcodes = cheatcodes
+
+ @staticmethod
+ def from_dict(d: dict) -> "Cheatcodes":
+ return Cheatcodes(
+ errors=[Error.from_dict(e) for e in d["errors"]],
+ events=[Event.from_dict(e) for e in d["events"]],
+ enums=[Enum.from_dict(e) for e in d["enums"]],
+ structs=[Struct.from_dict(e) for e in d["structs"]],
+ cheatcodes=[Cheatcode.from_dict(e) for e in d["cheatcodes"]],
+ )
+
+ @staticmethod
+ def from_json(s) -> "Cheatcodes":
+ return Cheatcodes.from_dict(json.loads(s))
+
+ @staticmethod
+ def from_json_file(file_path: str) -> "Cheatcodes":
+ with open(file_path, "r") as f:
+ return Cheatcodes.from_dict(json.load(f))
+
+
+class Item(PyEnum):
+ ERROR: str = "error"
+ EVENT: str = "event"
+ ENUM: str = "enum"
+ STRUCT: str = "struct"
+ FUNCTION: str = "function"
+
+
+class ItemOrder:
+ _list: list[Item]
+
+ def __init__(self, list: list[Item]) -> None:
+ assert len(list) <= len(Item), "list must not contain more items than Item"
+ assert len(list) == len(set(list)), "list must not contain duplicates"
+ self._list = list
+ pass
+
+ def get_list(self) -> list[Item]:
+ return self._list
+
+ @staticmethod
+ def default() -> "ItemOrder":
+ return ItemOrder(
+ [
+ Item.ERROR,
+ Item.EVENT,
+ Item.ENUM,
+ Item.STRUCT,
+ Item.FUNCTION,
+ ]
+ )
+
+
+class CheatcodesPrinter:
+ buffer: str
+
+ prelude: bool
+ spdx_identifier: str
+ solidity_requirement: str
+ abicoder_v2: bool
+
+ block_doc_style: bool
+
+ indent_level: int
+ _indent_str: str
+
+ nl_str: str
+
+ items_order: ItemOrder
+
+ def __init__(
+ self,
+ buffer: str = "",
+ prelude: bool = True,
+ spdx_identifier: str = "UNLICENSED",
+ solidity_requirement: str = "",
+ abicoder_pragma: bool = False,
+ block_doc_style: bool = False,
+ indent_level: int = 0,
+ indent_with: int | str = 4,
+ nl_str: str = "\n",
+ items_order: ItemOrder = ItemOrder.default(),
+ ):
+ self.prelude = prelude
+ self.spdx_identifier = spdx_identifier
+ self.solidity_requirement = solidity_requirement
+ self.abicoder_v2 = abicoder_pragma
+ self.block_doc_style = block_doc_style
+ self.buffer = buffer
+ self.indent_level = indent_level
+ self.nl_str = nl_str
+
+ if isinstance(indent_with, int):
+ assert indent_with >= 0
+ self._indent_str = " " * indent_with
+ elif isinstance(indent_with, str):
+ self._indent_str = indent_with
+ else:
+ assert False, "indent_with must be int or str"
+
+ self.items_order = items_order
+
+ def finish(self) -> str:
+ ret = self.buffer.rstrip()
+ self.buffer = ""
+ return ret
+
+ def p_contract(self, contract: Cheatcodes, name: str, inherits: str = ""):
+ if self.prelude:
+ self.p_prelude(contract)
+
+ self._p_str("interface ")
+ name = name.strip()
+ if name != "":
+ self._p_str(name)
+ self._p_str(" ")
+ if inherits != "":
+ self._p_str("is ")
+ self._p_str(inherits)
+ self._p_str(" ")
+ self._p_str("{")
+ self._p_nl()
+ self._with_indent(lambda: self._p_items(contract))
+ self._p_str("}")
+ self._p_nl()
+
+ def _p_items(self, contract: Cheatcodes):
+ for item in self.items_order.get_list():
+ if item == Item.ERROR:
+ self.p_errors(contract.errors)
+ elif item == Item.EVENT:
+ self.p_events(contract.events)
+ elif item == Item.ENUM:
+ self.p_enums(contract.enums)
+ elif item == Item.STRUCT:
+ self.p_structs(contract.structs)
+ elif item == Item.FUNCTION:
+ self.p_functions(contract.cheatcodes)
+ else:
+ assert False, f"unknown item {item}"
+
+ def p_prelude(self, contract: Cheatcodes | None = None):
+ self._p_str(f"// SPDX-License-Identifier: {self.spdx_identifier}")
+ self._p_nl()
+
+ if self.solidity_requirement != "":
+ req = self.solidity_requirement
+ elif contract and len(contract.errors) > 0:
+ req = ">=0.8.4 <0.9.0"
+ else:
+ req = ">=0.6.0 <0.9.0"
+ self._p_str(f"pragma solidity {req};")
+ self._p_nl()
+
+ if self.abicoder_v2:
+ self._p_str("pragma experimental ABIEncoderV2;")
+ self._p_nl()
+
+ self._p_nl()
+
+ def p_errors(self, errors: list[Error]):
+ for error in errors:
+ self._p_line(lambda: self.p_error(error))
+
+ def p_error(self, error: Error):
+ self._p_comment(error.description, doc=True)
+ self._p_line(lambda: self._p_str(error.declaration))
+
+ def p_events(self, events: list[Event]):
+ for event in events:
+ self._p_line(lambda: self.p_event(event))
+
+ def p_event(self, event: Event):
+ self._p_comment(event.description, doc=True)
+ self._p_line(lambda: self._p_str(event.declaration))
+
+ def p_enums(self, enums: list[Enum]):
+ for enum in enums:
+ self._p_line(lambda: self.p_enum(enum))
+
+ def p_enum(self, enum: Enum):
+ self._p_comment(enum.description, doc=True)
+ self._p_line(lambda: self._p_str(f"enum {enum.name} {{"))
+ self._with_indent(lambda: self.p_enum_variants(enum.variants))
+ self._p_line(lambda: self._p_str("}"))
+
+ def p_enum_variants(self, variants: list[EnumVariant]):
+ for i, variant in enumerate(variants):
+ self._p_indent()
+ self._p_comment(variant.description)
+
+ self._p_indent()
+ self._p_str(variant.name)
+ if i < len(variants) - 1:
+ self._p_str(",")
+ self._p_nl()
+
+ def p_structs(self, structs: list[Struct]):
+ for struct in structs:
+ self._p_line(lambda: self.p_struct(struct))
+
+ def p_struct(self, struct: Struct):
+ self._p_comment(struct.description, doc=True)
+ self._p_line(lambda: self._p_str(f"struct {struct.name} {{"))
+ self._with_indent(lambda: self.p_struct_fields(struct.fields))
+ self._p_line(lambda: self._p_str("}"))
+
+ def p_struct_fields(self, fields: list[StructField]):
+ for field in fields:
+ self._p_line(lambda: self.p_struct_field(field))
+
+ def p_struct_field(self, field: StructField):
+ self._p_comment(field.description)
+ self._p_indented(lambda: self._p_str(f"{field.ty} {field.name};"))
+
+ def p_functions(self, cheatcodes: list[Cheatcode]):
+ for cheatcode in cheatcodes:
+ self._p_line(lambda: self.p_function(cheatcode.func))
+
+ def p_function(self, func: Function):
+ self._p_comment(func.description, doc=True)
+ self._p_line(lambda: self._p_str(func.declaration))
+
+ def _p_comment(self, s: str, doc: bool = False):
+ s = s.strip()
+ if s == "":
+ return
+
+ s = map(lambda line: line.lstrip(), s.split("\n"))
+ if self.block_doc_style:
+ self._p_str("/*")
+ if doc:
+ self._p_str("*")
+ self._p_nl()
+ for line in s:
+ self._p_indent()
+ self._p_str(" ")
+ if doc:
+ self._p_str("* ")
+ self._p_str(line)
+ self._p_nl()
+ self._p_indent()
+ self._p_str(" */")
+ self._p_nl()
+ else:
+ first_line = True
+ for line in s:
+ if not first_line:
+ self._p_indent()
+ first_line = False
+
+ if doc:
+ self._p_str("/// ")
+ else:
+ self._p_str("// ")
+ self._p_str(line)
+ self._p_nl()
+
+ def _with_indent(self, f: VoidFn):
+ self._inc_indent()
+ f()
+ self._dec_indent()
+
+ def _p_line(self, f: VoidFn):
+ self._p_indent()
+ f()
+ self._p_nl()
+
+ def _p_indented(self, f: VoidFn):
+ self._p_indent()
+ f()
+
+ def _p_indent(self):
+ for _ in range(self.indent_level):
+ self._p_str(self._indent_str)
+
+ def _p_nl(self):
+ self._p_str(self.nl_str)
+
+ def _p_str(self, txt: str):
+ self.buffer += txt
+
+ def _inc_indent(self):
+ self.indent_level += 1
+
+ def _dec_indent(self):
+ self.indent_level -= 1
+
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Base.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Base.sol
new file mode 100644
index 000000000..851ac0cd2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Base.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {StdStorage} from "./StdStorage.sol";
+import {Vm, VmSafe} from "./Vm.sol";
+
+abstract contract CommonBase {
+ // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
+ address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
+ // console.sol and console2.sol work by executing a staticcall to this address.
+ address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67;
+ // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
+ address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+ // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.
+ address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller"))));
+ // Address of the test contract, deployed by the DEFAULT_SENDER.
+ address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
+ // Deterministic deployment address of the Multicall3 contract.
+ address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11;
+ // The order of the secp256k1 curve.
+ uint256 internal constant SECP256K1_ORDER =
+ 115792089237316195423570985008687907852837564279074904382605163141518161494337;
+
+ uint256 internal constant UINT256_MAX =
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ Vm internal constant vm = Vm(VM_ADDRESS);
+ StdStorage internal stdstore;
+}
+
+abstract contract TestBase is CommonBase {}
+
+abstract contract ScriptBase is CommonBase {
+ VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Script.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Script.sol
new file mode 100644
index 000000000..94e75f6cb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Script.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+// 💬 ABOUT
+// Forge Std's default Script.
+
+// 🧩 MODULES
+import {console} from "./console.sol";
+import {console2} from "./console2.sol";
+import {safeconsole} from "./safeconsole.sol";
+import {StdChains} from "./StdChains.sol";
+import {StdCheatsSafe} from "./StdCheats.sol";
+import {stdJson} from "./StdJson.sol";
+import {stdMath} from "./StdMath.sol";
+import {StdStorage, stdStorageSafe} from "./StdStorage.sol";
+import {StdStyle} from "./StdStyle.sol";
+import {StdUtils} from "./StdUtils.sol";
+import {VmSafe} from "./Vm.sol";
+
+// 📦 BOILERPLATE
+import {ScriptBase} from "./Base.sol";
+
+// ⭐️ SCRIPT
+abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils {
+ // Note: IS_SCRIPT() must return true.
+ bool public IS_SCRIPT = true;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdAssertions.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdAssertions.sol
new file mode 100644
index 000000000..857ecd570
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdAssertions.sol
@@ -0,0 +1,669 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+import {Vm} from "./Vm.sol";
+
+abstract contract StdAssertions {
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ event log(string);
+ event logs(bytes);
+
+ event log_address(address);
+ event log_bytes32(bytes32);
+ event log_int(int256);
+ event log_uint(uint256);
+ event log_bytes(bytes);
+ event log_string(string);
+
+ event log_named_address(string key, address val);
+ event log_named_bytes32(string key, bytes32 val);
+ event log_named_decimal_int(string key, int256 val, uint256 decimals);
+ event log_named_decimal_uint(string key, uint256 val, uint256 decimals);
+ event log_named_int(string key, int256 val);
+ event log_named_uint(string key, uint256 val);
+ event log_named_bytes(string key, bytes val);
+ event log_named_string(string key, string val);
+
+ event log_array(uint256[] val);
+ event log_array(int256[] val);
+ event log_array(address[] val);
+ event log_named_array(string key, uint256[] val);
+ event log_named_array(string key, int256[] val);
+ event log_named_array(string key, address[] val);
+
+ bool private _failed;
+
+ function failed() public view returns (bool) {
+ if (_failed) {
+ return _failed;
+ } else {
+ return vm.load(address(vm), bytes32("failed")) != bytes32(0);
+ }
+ }
+
+ function fail() internal virtual {
+ vm.store(address(vm), bytes32("failed"), bytes32(uint256(1)));
+ _failed = true;
+ }
+
+ function assertTrue(bool data) internal pure virtual {
+ vm.assertTrue(data);
+ }
+
+ function assertTrue(bool data, string memory err) internal pure virtual {
+ vm.assertTrue(data, err);
+ }
+
+ function assertFalse(bool data) internal pure virtual {
+ vm.assertFalse(data);
+ }
+
+ function assertFalse(bool data, string memory err) internal pure virtual {
+ vm.assertFalse(data, err);
+ }
+
+ function assertEq(bool left, bool right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bool left, bool right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(uint256 left, uint256 right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(uint256 left, uint256 right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals);
+ }
+
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals, err);
+ }
+
+ function assertEq(int256 left, int256 right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(int256 left, int256 right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals);
+ }
+
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertEqDecimal(left, right, decimals, err);
+ }
+
+ function assertEq(address left, address right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(address left, address right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes32 left, bytes32 right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq32(bytes32 left, bytes32 right) internal pure virtual {
+ assertEq(left, right);
+ }
+
+ function assertEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ assertEq(left, right, err);
+ }
+
+ function assertEq(string memory left, string memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(string memory left, string memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes memory left, bytes memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bool[] memory left, bool[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(int256[] memory left, int256[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(address[] memory left, address[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(string[] memory left, string[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ function assertEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
+ vm.assertEq(left, right);
+ }
+
+ function assertEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
+ vm.assertEq(left, right, err);
+ }
+
+ // Legacy helper
+ function assertEqUint(uint256 left, uint256 right) internal pure virtual {
+ assertEq(left, right);
+ }
+
+ function assertNotEq(bool left, bool right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bool left, bool right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(uint256 left, uint256 right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(uint256 left, uint256 right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertNotEqDecimal(left, right, decimals);
+ }
+
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string memory err)
+ internal
+ pure
+ virtual
+ {
+ vm.assertNotEqDecimal(left, right, decimals, err);
+ }
+
+ function assertNotEq(int256 left, int256 right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(int256 left, int256 right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertNotEqDecimal(left, right, decimals);
+ }
+
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertNotEqDecimal(left, right, decimals, err);
+ }
+
+ function assertNotEq(address left, address right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(address left, address right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes32 left, bytes32 right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq32(bytes32 left, bytes32 right) internal pure virtual {
+ assertNotEq(left, right);
+ }
+
+ function assertNotEq32(bytes32 left, bytes32 right, string memory err) internal pure virtual {
+ assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(string memory left, string memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(string memory left, string memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes memory left, bytes memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bool[] memory left, bool[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bool[] memory left, bool[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(uint256[] memory left, uint256[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(uint256[] memory left, uint256[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(int256[] memory left, int256[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(int256[] memory left, int256[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(address[] memory left, address[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(address[] memory left, address[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes32[] memory left, bytes32[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes32[] memory left, bytes32[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(string[] memory left, string[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(string[] memory left, string[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertNotEq(bytes[] memory left, bytes[] memory right) internal pure virtual {
+ vm.assertNotEq(left, right);
+ }
+
+ function assertNotEq(bytes[] memory left, bytes[] memory right, string memory err) internal pure virtual {
+ vm.assertNotEq(left, right, err);
+ }
+
+ function assertLt(uint256 left, uint256 right) internal pure virtual {
+ vm.assertLt(left, right);
+ }
+
+ function assertLt(uint256 left, uint256 right, string memory err) internal pure virtual {
+ vm.assertLt(left, right, err);
+ }
+
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals);
+ }
+
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals, err);
+ }
+
+ function assertLt(int256 left, int256 right) internal pure virtual {
+ vm.assertLt(left, right);
+ }
+
+ function assertLt(int256 left, int256 right, string memory err) internal pure virtual {
+ vm.assertLt(left, right, err);
+ }
+
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals);
+ }
+
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLtDecimal(left, right, decimals, err);
+ }
+
+ function assertGt(uint256 left, uint256 right) internal pure virtual {
+ vm.assertGt(left, right);
+ }
+
+ function assertGt(uint256 left, uint256 right, string memory err) internal pure virtual {
+ vm.assertGt(left, right, err);
+ }
+
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals);
+ }
+
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals, err);
+ }
+
+ function assertGt(int256 left, int256 right) internal pure virtual {
+ vm.assertGt(left, right);
+ }
+
+ function assertGt(int256 left, int256 right, string memory err) internal pure virtual {
+ vm.assertGt(left, right, err);
+ }
+
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals);
+ }
+
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGtDecimal(left, right, decimals, err);
+ }
+
+ function assertLe(uint256 left, uint256 right) internal pure virtual {
+ vm.assertLe(left, right);
+ }
+
+ function assertLe(uint256 left, uint256 right, string memory err) internal pure virtual {
+ vm.assertLe(left, right, err);
+ }
+
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals);
+ }
+
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals, err);
+ }
+
+ function assertLe(int256 left, int256 right) internal pure virtual {
+ vm.assertLe(left, right);
+ }
+
+ function assertLe(int256 left, int256 right, string memory err) internal pure virtual {
+ vm.assertLe(left, right, err);
+ }
+
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals);
+ }
+
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertLeDecimal(left, right, decimals, err);
+ }
+
+ function assertGe(uint256 left, uint256 right) internal pure virtual {
+ vm.assertGe(left, right);
+ }
+
+ function assertGe(uint256 left, uint256 right, string memory err) internal pure virtual {
+ vm.assertGe(left, right, err);
+ }
+
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals);
+ }
+
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals, err);
+ }
+
+ function assertGe(int256 left, int256 right) internal pure virtual {
+ vm.assertGe(left, right);
+ }
+
+ function assertGe(int256 left, int256 right, string memory err) internal pure virtual {
+ vm.assertGe(left, right, err);
+ }
+
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals);
+ }
+
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals, string memory err) internal pure virtual {
+ vm.assertGeDecimal(left, right, decimals, err);
+ }
+
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) internal pure virtual {
+ vm.assertApproxEqAbs(left, right, maxDelta);
+ }
+
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string memory err)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbs(left, right, maxDelta, err);
+ }
+
+ function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
+ }
+
+ function assertApproxEqAbsDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxDelta,
+ uint256 decimals,
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
+ }
+
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) internal pure virtual {
+ vm.assertApproxEqAbs(left, right, maxDelta);
+ }
+
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string memory err) internal pure virtual {
+ vm.assertApproxEqAbs(left, right, maxDelta, err);
+ }
+
+ function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals);
+ }
+
+ function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals, string memory err)
+ internal
+ pure
+ virtual
+ {
+ vm.assertApproxEqAbsDecimal(left, right, maxDelta, decimals, err);
+ }
+
+ function assertApproxEqRel(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%
+ ) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta);
+ }
+
+ function assertApproxEqRel(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta, err);
+ }
+
+ function assertApproxEqRelDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
+ }
+
+ function assertApproxEqRelDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals,
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
+ }
+
+ function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta);
+ }
+
+ function assertApproxEqRel(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRel(left, right, maxPercentDelta, err);
+ }
+
+ function assertApproxEqRelDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals);
+ }
+
+ function assertApproxEqRelDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%
+ uint256 decimals,
+ string memory err
+ ) internal pure virtual {
+ vm.assertApproxEqRelDecimal(left, right, maxPercentDelta, decimals, err);
+ }
+
+ // Inherited from DSTest, not used but kept for backwards-compatibility
+ function checkEq0(bytes memory left, bytes memory right) internal pure returns (bool) {
+ return keccak256(left) == keccak256(right);
+ }
+
+ function assertEq0(bytes memory left, bytes memory right) internal pure virtual {
+ assertEq(left, right);
+ }
+
+ function assertEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ assertEq(left, right, err);
+ }
+
+ function assertNotEq0(bytes memory left, bytes memory right) internal pure virtual {
+ assertNotEq(left, right);
+ }
+
+ function assertNotEq0(bytes memory left, bytes memory right, string memory err) internal pure virtual {
+ assertNotEq(left, right, err);
+ }
+
+ function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB) internal virtual {
+ assertEqCall(target, callDataA, target, callDataB, true);
+ }
+
+ function assertEqCall(address targetA, bytes memory callDataA, address targetB, bytes memory callDataB)
+ internal
+ virtual
+ {
+ assertEqCall(targetA, callDataA, targetB, callDataB, true);
+ }
+
+ function assertEqCall(address target, bytes memory callDataA, bytes memory callDataB, bool strictRevertData)
+ internal
+ virtual
+ {
+ assertEqCall(target, callDataA, target, callDataB, strictRevertData);
+ }
+
+ function assertEqCall(
+ address targetA,
+ bytes memory callDataA,
+ address targetB,
+ bytes memory callDataB,
+ bool strictRevertData
+ ) internal virtual {
+ (bool successA, bytes memory returnDataA) = address(targetA).call(callDataA);
+ (bool successB, bytes memory returnDataB) = address(targetB).call(callDataB);
+
+ if (successA && successB) {
+ assertEq(returnDataA, returnDataB, "Call return data does not match");
+ }
+
+ if (!successA && !successB && strictRevertData) {
+ assertEq(returnDataA, returnDataB, "Call revert data does not match");
+ }
+
+ if (!successA && successB) {
+ emit log("Error: Calls were not equal");
+ emit log_named_bytes(" Left call revert data", returnDataA);
+ emit log_named_bytes(" Right call return data", returnDataB);
+ revert("assertion failed");
+ }
+
+ if (successA && !successB) {
+ emit log("Error: Calls were not equal");
+ emit log_named_bytes(" Left call return data", returnDataA);
+ emit log_named_bytes(" Right call revert data", returnDataB);
+ revert("assertion failed");
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdChains.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdChains.sol
new file mode 100644
index 000000000..9ca1b82d9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdChains.sol
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {VmSafe} from "./Vm.sol";
+
+/**
+ * StdChains provides information about EVM compatible chains that can be used in scripts/tests.
+ * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
+ * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
+ * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
+ * alias used in this contract, which can be found as the first argument to the
+ * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
+ *
+ * There are two main ways to use this contract:
+ * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
+ * `setChain(string memory chainAlias, Chain memory chain)`
+ * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
+ *
+ * The first time either of those are used, chains are initialized with the default set of RPC URLs.
+ * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
+ * `defaultRpcUrls`.
+ *
+ * The `setChain` function is straightforward, and it simply saves off the given chain data.
+ *
+ * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
+ * we want to retrieve the RPC URL for `mainnet`:
+ * - If you have specified data with `setChain`, it will return that.
+ * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
+ * is valid (e.g. a URL is specified, or an environment variable is given and exists).
+ * - If neither of the above conditions is met, the default data is returned.
+ *
+ * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
+ */
+abstract contract StdChains {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ bool private stdChainsInitialized;
+
+ struct ChainData {
+ string name;
+ uint256 chainId;
+ string rpcUrl;
+ }
+
+ struct Chain {
+ // The chain name.
+ string name;
+ // The chain's Chain ID.
+ uint256 chainId;
+ // The chain's alias. (i.e. what gets specified in `foundry.toml`).
+ string chainAlias;
+ // A default RPC endpoint for this chain.
+ // NOTE: This default RPC URL is included for convenience to facilitate quick tests and
+ // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy
+ // usage as you will be throttled and this is a disservice to others who need this endpoint.
+ string rpcUrl;
+ }
+
+ // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.
+ mapping(string => Chain) private chains;
+ // Maps from the chain's alias to it's default RPC URL.
+ mapping(string => string) private defaultRpcUrls;
+ // Maps from a chain ID to it's alias.
+ mapping(uint256 => string) private idToAlias;
+
+ bool private fallbackToDefaultRpcUrls = true;
+
+ // The RPC URL will be fetched from config or defaultRpcUrls if possible.
+ function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) {
+ require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string.");
+
+ initializeStdChains();
+ chain = chains[chainAlias];
+ require(
+ chain.chainId != 0,
+ string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
+ );
+
+ chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
+ }
+
+ function getChain(uint256 chainId) internal virtual returns (Chain memory chain) {
+ require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0.");
+ initializeStdChains();
+ string memory chainAlias = idToAlias[chainId];
+
+ chain = chains[chainAlias];
+
+ require(
+ chain.chainId != 0,
+ string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
+ );
+
+ chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
+ }
+
+ // set chain info, with priority to argument's rpcUrl field.
+ function setChain(string memory chainAlias, ChainData memory chain) internal virtual {
+ require(
+ bytes(chainAlias).length != 0,
+ "StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
+ );
+
+ require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
+
+ initializeStdChains();
+ string memory foundAlias = idToAlias[chain.chainId];
+
+ require(
+ bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)),
+ string(
+ abi.encodePacked(
+ "StdChains setChain(string,ChainData): Chain ID ",
+ vm.toString(chain.chainId),
+ " already used by \"",
+ foundAlias,
+ "\"."
+ )
+ )
+ );
+
+ uint256 oldChainId = chains[chainAlias].chainId;
+ delete idToAlias[oldChainId];
+
+ chains[chainAlias] =
+ Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
+ idToAlias[chain.chainId] = chainAlias;
+ }
+
+ // set chain info, with priority to argument's rpcUrl field.
+ function setChain(string memory chainAlias, Chain memory chain) internal virtual {
+ setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
+ }
+
+ function _toUpper(string memory str) private pure returns (string memory) {
+ bytes memory strb = bytes(str);
+ bytes memory copy = new bytes(strb.length);
+ for (uint256 i = 0; i < strb.length; i++) {
+ bytes1 b = strb[i];
+ if (b >= 0x61 && b <= 0x7A) {
+ copy[i] = bytes1(uint8(b) - 32);
+ } else {
+ copy[i] = b;
+ }
+ }
+ return string(copy);
+ }
+
+ // lookup rpcUrl, in descending order of priority:
+ // current -> config (foundry.toml) -> environment variable -> default
+ function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain)
+ private
+ view
+ returns (Chain memory)
+ {
+ if (bytes(chain.rpcUrl).length == 0) {
+ try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) {
+ chain.rpcUrl = configRpcUrl;
+ } catch (bytes memory err) {
+ string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
+ if (fallbackToDefaultRpcUrls) {
+ chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
+ } else {
+ chain.rpcUrl = vm.envString(envName);
+ }
+ // Distinguish 'not found' from 'cannot read'
+ // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions
+ bytes memory oldNotFoundError =
+ abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
+ bytes memory newNotFoundError = abi.encodeWithSignature(
+ "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
+ );
+ bytes32 errHash = keccak256(err);
+ if (
+ (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError))
+ || bytes(chain.rpcUrl).length == 0
+ ) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ revert(add(32, err), mload(err))
+ }
+ }
+ }
+ }
+ return chain;
+ }
+
+ function setFallbackToDefaultRpcUrls(bool useDefault) internal {
+ fallbackToDefaultRpcUrls = useDefault;
+ }
+
+ function initializeStdChains() private {
+ if (stdChainsInitialized) return;
+
+ stdChainsInitialized = true;
+
+ // If adding an RPC here, make sure to test the default RPC URL in `test_Rpcs` in `StdChains.t.sol`
+ setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
+ setChainWithDefaultRpcUrl(
+ "mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP")
+ );
+ setChainWithDefaultRpcUrl(
+ "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
+ );
+ setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
+ setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
+ setChainWithDefaultRpcUrl(
+ "optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
+ );
+ setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
+ setChainWithDefaultRpcUrl(
+ "arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
+ );
+ setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
+ setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
+ setChainWithDefaultRpcUrl(
+ "polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
+ );
+ setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
+ setChainWithDefaultRpcUrl(
+ "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
+ );
+ setChainWithDefaultRpcUrl(
+ "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
+ );
+ setChainWithDefaultRpcUrl(
+ "bnb_smart_chain_testnet",
+ ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
+ );
+ setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
+ setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
+ setChainWithDefaultRpcUrl(
+ "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
+ );
+ setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
+ setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
+ setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
+ setChainWithDefaultRpcUrl("blast_sepolia", ChainData("Blast Sepolia", 168587773, "https://sepolia.blast.io"));
+ setChainWithDefaultRpcUrl("blast", ChainData("Blast", 81457, "https://rpc.blast.io"));
+ setChainWithDefaultRpcUrl("fantom_opera", ChainData("Fantom Opera", 250, "https://rpc.ankr.com/fantom/"));
+ setChainWithDefaultRpcUrl(
+ "fantom_opera_testnet", ChainData("Fantom Opera Testnet", 4002, "https://rpc.ankr.com/fantom_testnet/")
+ );
+ setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
+ setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
+ setChainWithDefaultRpcUrl(
+ "berachain_bartio_testnet", ChainData("Berachain bArtio Testnet", 80084, "https://bartio.rpc.berachain.com")
+ );
+ setChainWithDefaultRpcUrl("flare", ChainData("Flare", 14, "https://flare-api.flare.network/ext/C/rpc"));
+ setChainWithDefaultRpcUrl(
+ "flare_coston2", ChainData("Flare Coston2", 114, "https://coston2-api.flare.network/ext/C/rpc")
+ );
+ }
+
+ // set chain info, with priority to chainAlias' rpc url in foundry.toml
+ function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private {
+ string memory rpcUrl = chain.rpcUrl;
+ defaultRpcUrls[chainAlias] = rpcUrl;
+ chain.rpcUrl = "";
+ setChain(chainAlias, chain);
+ chain.rpcUrl = rpcUrl; // restore argument
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdCheats.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdCheats.sol
new file mode 100644
index 000000000..95850d118
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdCheats.sol
@@ -0,0 +1,817 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {StdStorage, stdStorage} from "./StdStorage.sol";
+import {console2} from "./console2.sol";
+import {Vm} from "./Vm.sol";
+
+abstract contract StdCheatsSafe {
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ uint256 private constant UINT256_MAX =
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ bool private gasMeteringOff;
+
+ // Data structures to parse Transaction objects from the broadcast artifact
+ // that conform to EIP1559. The Raw structs is what is parsed from the JSON
+ // and then converted to the one that is used by the user for better UX.
+
+ struct RawTx1559 {
+ string[] arguments;
+ address contractAddress;
+ string contractName;
+ // json value name = function
+ string functionSig;
+ bytes32 hash;
+ // json value name = tx
+ RawTx1559Detail txDetail;
+ // json value name = type
+ string opcode;
+ }
+
+ struct RawTx1559Detail {
+ AccessList[] accessList;
+ bytes data;
+ address from;
+ bytes gas;
+ bytes nonce;
+ address to;
+ bytes txType;
+ bytes value;
+ }
+
+ struct Tx1559 {
+ string[] arguments;
+ address contractAddress;
+ string contractName;
+ string functionSig;
+ bytes32 hash;
+ Tx1559Detail txDetail;
+ string opcode;
+ }
+
+ struct Tx1559Detail {
+ AccessList[] accessList;
+ bytes data;
+ address from;
+ uint256 gas;
+ uint256 nonce;
+ address to;
+ uint256 txType;
+ uint256 value;
+ }
+
+ // Data structures to parse Transaction objects from the broadcast artifact
+ // that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON
+ // and then converted to the one that is used by the user for better UX.
+
+ struct TxLegacy {
+ string[] arguments;
+ address contractAddress;
+ string contractName;
+ string functionSig;
+ string hash;
+ string opcode;
+ TxDetailLegacy transaction;
+ }
+
+ struct TxDetailLegacy {
+ AccessList[] accessList;
+ uint256 chainId;
+ bytes data;
+ address from;
+ uint256 gas;
+ uint256 gasPrice;
+ bytes32 hash;
+ uint256 nonce;
+ bytes1 opcode;
+ bytes32 r;
+ bytes32 s;
+ uint256 txType;
+ address to;
+ uint8 v;
+ uint256 value;
+ }
+
+ struct AccessList {
+ address accessAddress;
+ bytes32[] storageKeys;
+ }
+
+ // Data structures to parse Receipt objects from the broadcast artifact.
+ // The Raw structs is what is parsed from the JSON
+ // and then converted to the one that is used by the user for better UX.
+
+ struct RawReceipt {
+ bytes32 blockHash;
+ bytes blockNumber;
+ address contractAddress;
+ bytes cumulativeGasUsed;
+ bytes effectiveGasPrice;
+ address from;
+ bytes gasUsed;
+ RawReceiptLog[] logs;
+ bytes logsBloom;
+ bytes status;
+ address to;
+ bytes32 transactionHash;
+ bytes transactionIndex;
+ }
+
+ struct Receipt {
+ bytes32 blockHash;
+ uint256 blockNumber;
+ address contractAddress;
+ uint256 cumulativeGasUsed;
+ uint256 effectiveGasPrice;
+ address from;
+ uint256 gasUsed;
+ ReceiptLog[] logs;
+ bytes logsBloom;
+ uint256 status;
+ address to;
+ bytes32 transactionHash;
+ uint256 transactionIndex;
+ }
+
+ // Data structures to parse the entire broadcast artifact, assuming the
+ // transactions conform to EIP1559.
+
+ struct EIP1559ScriptArtifact {
+ string[] libraries;
+ string path;
+ string[] pending;
+ Receipt[] receipts;
+ uint256 timestamp;
+ Tx1559[] transactions;
+ TxReturn[] txReturns;
+ }
+
+ struct RawEIP1559ScriptArtifact {
+ string[] libraries;
+ string path;
+ string[] pending;
+ RawReceipt[] receipts;
+ TxReturn[] txReturns;
+ uint256 timestamp;
+ RawTx1559[] transactions;
+ }
+
+ struct RawReceiptLog {
+ // json value = address
+ address logAddress;
+ bytes32 blockHash;
+ bytes blockNumber;
+ bytes data;
+ bytes logIndex;
+ bool removed;
+ bytes32[] topics;
+ bytes32 transactionHash;
+ bytes transactionIndex;
+ bytes transactionLogIndex;
+ }
+
+ struct ReceiptLog {
+ // json value = address
+ address logAddress;
+ bytes32 blockHash;
+ uint256 blockNumber;
+ bytes data;
+ uint256 logIndex;
+ bytes32[] topics;
+ uint256 transactionIndex;
+ uint256 transactionLogIndex;
+ bool removed;
+ }
+
+ struct TxReturn {
+ string internalType;
+ string value;
+ }
+
+ struct Account {
+ address addr;
+ uint256 key;
+ }
+
+ enum AddressType {
+ Payable,
+ NonPayable,
+ ZeroAddress,
+ Precompile,
+ ForgeAddress
+ }
+
+ // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
+ function assumeNotBlacklisted(address token, address addr) internal view virtual {
+ // Nothing to check if `token` is not a contract.
+ uint256 tokenCodeSize;
+ assembly {
+ tokenCodeSize := extcodesize(token)
+ }
+ require(tokenCodeSize > 0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
+
+ bool success;
+ bytes memory returnData;
+
+ // 4-byte selector for `isBlacklisted(address)`, used by USDC.
+ (success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
+ vm.assume(!success || abi.decode(returnData, (bool)) == false);
+
+ // 4-byte selector for `isBlackListed(address)`, used by USDT.
+ (success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
+ vm.assume(!success || abi.decode(returnData, (bool)) == false);
+ }
+
+ // Checks that `addr` is not blacklisted by token contracts that have a blacklist.
+ // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for
+ // backwards compatibility, since this name was used in the original PR which already has
+ // a release. This function can be removed in a future release once we want a breaking change.
+ function assumeNoBlacklisted(address token, address addr) internal view virtual {
+ assumeNotBlacklisted(token, addr);
+ }
+
+ function assumeAddressIsNot(address addr, AddressType addressType) internal virtual {
+ if (addressType == AddressType.Payable) {
+ assumeNotPayable(addr);
+ } else if (addressType == AddressType.NonPayable) {
+ assumePayable(addr);
+ } else if (addressType == AddressType.ZeroAddress) {
+ assumeNotZeroAddress(addr);
+ } else if (addressType == AddressType.Precompile) {
+ assumeNotPrecompile(addr);
+ } else if (addressType == AddressType.ForgeAddress) {
+ assumeNotForgeAddress(addr);
+ }
+ }
+
+ function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual {
+ assumeAddressIsNot(addr, addressType1);
+ assumeAddressIsNot(addr, addressType2);
+ }
+
+ function assumeAddressIsNot(
+ address addr,
+ AddressType addressType1,
+ AddressType addressType2,
+ AddressType addressType3
+ ) internal virtual {
+ assumeAddressIsNot(addr, addressType1);
+ assumeAddressIsNot(addr, addressType2);
+ assumeAddressIsNot(addr, addressType3);
+ }
+
+ function assumeAddressIsNot(
+ address addr,
+ AddressType addressType1,
+ AddressType addressType2,
+ AddressType addressType3,
+ AddressType addressType4
+ ) internal virtual {
+ assumeAddressIsNot(addr, addressType1);
+ assumeAddressIsNot(addr, addressType2);
+ assumeAddressIsNot(addr, addressType3);
+ assumeAddressIsNot(addr, addressType4);
+ }
+
+ // This function checks whether an address, `addr`, is payable. It works by sending 1 wei to
+ // `addr` and checking the `success` return value.
+ // NOTE: This function may result in state changes depending on the fallback/receive logic
+ // implemented by `addr`, which should be taken into account when this function is used.
+ function _isPayable(address addr) private returns (bool) {
+ require(
+ addr.balance < UINT256_MAX,
+ "StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
+ );
+ uint256 origBalanceTest = address(this).balance;
+ uint256 origBalanceAddr = address(addr).balance;
+
+ vm.deal(address(this), 1);
+ (bool success,) = payable(addr).call{value: 1}("");
+
+ // reset balances
+ vm.deal(address(this), origBalanceTest);
+ vm.deal(addr, origBalanceAddr);
+
+ return success;
+ }
+
+ // NOTE: This function may result in state changes depending on the fallback/receive logic
+ // implemented by `addr`, which should be taken into account when this function is used. See the
+ // `_isPayable` method for more information.
+ function assumePayable(address addr) internal virtual {
+ vm.assume(_isPayable(addr));
+ }
+
+ function assumeNotPayable(address addr) internal virtual {
+ vm.assume(!_isPayable(addr));
+ }
+
+ function assumeNotZeroAddress(address addr) internal pure virtual {
+ vm.assume(addr != address(0));
+ }
+
+ function assumeNotPrecompile(address addr) internal pure virtual {
+ assumeNotPrecompile(addr, _pureChainId());
+ }
+
+ function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual {
+ // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific
+ // address), but the same rationale for excluding them applies so we include those too.
+
+ // These are reserved by Ethereum and may be on all EVM-compatible chains.
+ vm.assume(addr < address(0x1) || addr > address(0xff));
+
+ // forgefmt: disable-start
+ if (chainId == 10 || chainId == 420) {
+ // https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
+ vm.assume(addr < address(0x4200000000000000000000000000000000000000) || addr > address(0x4200000000000000000000000000000000000800));
+ } else if (chainId == 42161 || chainId == 421613) {
+ // https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
+ vm.assume(addr < address(0x0000000000000000000000000000000000000064) || addr > address(0x0000000000000000000000000000000000000068));
+ } else if (chainId == 43114 || chainId == 43113) {
+ // https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
+ vm.assume(addr < address(0x0100000000000000000000000000000000000000) || addr > address(0x01000000000000000000000000000000000000ff));
+ vm.assume(addr < address(0x0200000000000000000000000000000000000000) || addr > address(0x02000000000000000000000000000000000000FF));
+ vm.assume(addr < address(0x0300000000000000000000000000000000000000) || addr > address(0x03000000000000000000000000000000000000Ff));
+ }
+ // forgefmt: disable-end
+ }
+
+ function assumeNotForgeAddress(address addr) internal pure virtual {
+ // vm, console, and Create2Deployer addresses
+ vm.assume(
+ addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
+ && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
+ );
+ }
+
+ function readEIP1559ScriptArtifact(string memory path)
+ internal
+ view
+ virtual
+ returns (EIP1559ScriptArtifact memory)
+ {
+ string memory data = vm.readFile(path);
+ bytes memory parsedData = vm.parseJson(data);
+ RawEIP1559ScriptArtifact memory rawArtifact = abi.decode(parsedData, (RawEIP1559ScriptArtifact));
+ EIP1559ScriptArtifact memory artifact;
+ artifact.libraries = rawArtifact.libraries;
+ artifact.path = rawArtifact.path;
+ artifact.timestamp = rawArtifact.timestamp;
+ artifact.pending = rawArtifact.pending;
+ artifact.txReturns = rawArtifact.txReturns;
+ artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
+ artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
+ return artifact;
+ }
+
+ function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) {
+ Tx1559[] memory txs = new Tx1559[](rawTxs.length);
+ for (uint256 i; i < rawTxs.length; i++) {
+ txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
+ }
+ return txs;
+ }
+
+ function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) {
+ Tx1559 memory transaction;
+ transaction.arguments = rawTx.arguments;
+ transaction.contractName = rawTx.contractName;
+ transaction.functionSig = rawTx.functionSig;
+ transaction.hash = rawTx.hash;
+ transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
+ transaction.opcode = rawTx.opcode;
+ return transaction;
+ }
+
+ function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
+ internal
+ pure
+ virtual
+ returns (Tx1559Detail memory)
+ {
+ Tx1559Detail memory txDetail;
+ txDetail.data = rawDetail.data;
+ txDetail.from = rawDetail.from;
+ txDetail.to = rawDetail.to;
+ txDetail.nonce = _bytesToUint(rawDetail.nonce);
+ txDetail.txType = _bytesToUint(rawDetail.txType);
+ txDetail.value = _bytesToUint(rawDetail.value);
+ txDetail.gas = _bytesToUint(rawDetail.gas);
+ txDetail.accessList = rawDetail.accessList;
+ return txDetail;
+ }
+
+ function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) {
+ string memory deployData = vm.readFile(path);
+ bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions");
+ RawTx1559[] memory rawTxs = abi.decode(parsedDeployData, (RawTx1559[]));
+ return rawToConvertedEIPTx1559s(rawTxs);
+ }
+
+ function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) {
+ string memory deployData = vm.readFile(path);
+ string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
+ bytes memory parsedDeployData = vm.parseJson(deployData, key);
+ RawTx1559 memory rawTx = abi.decode(parsedDeployData, (RawTx1559));
+ return rawToConvertedEIPTx1559(rawTx);
+ }
+
+ // Analogous to readTransactions, but for receipts.
+ function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) {
+ string memory deployData = vm.readFile(path);
+ bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts");
+ RawReceipt[] memory rawReceipts = abi.decode(parsedDeployData, (RawReceipt[]));
+ return rawToConvertedReceipts(rawReceipts);
+ }
+
+ function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) {
+ string memory deployData = vm.readFile(path);
+ string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
+ bytes memory parsedDeployData = vm.parseJson(deployData, key);
+ RawReceipt memory rawReceipt = abi.decode(parsedDeployData, (RawReceipt));
+ return rawToConvertedReceipt(rawReceipt);
+ }
+
+ function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) {
+ Receipt[] memory receipts = new Receipt[](rawReceipts.length);
+ for (uint256 i; i < rawReceipts.length; i++) {
+ receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
+ }
+ return receipts;
+ }
+
+ function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) {
+ Receipt memory receipt;
+ receipt.blockHash = rawReceipt.blockHash;
+ receipt.to = rawReceipt.to;
+ receipt.from = rawReceipt.from;
+ receipt.contractAddress = rawReceipt.contractAddress;
+ receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
+ receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
+ receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
+ receipt.status = _bytesToUint(rawReceipt.status);
+ receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
+ receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
+ receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
+ receipt.logsBloom = rawReceipt.logsBloom;
+ receipt.transactionHash = rawReceipt.transactionHash;
+ return receipt;
+ }
+
+ function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
+ internal
+ pure
+ virtual
+ returns (ReceiptLog[] memory)
+ {
+ ReceiptLog[] memory logs = new ReceiptLog[](rawLogs.length);
+ for (uint256 i; i < rawLogs.length; i++) {
+ logs[i].logAddress = rawLogs[i].logAddress;
+ logs[i].blockHash = rawLogs[i].blockHash;
+ logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
+ logs[i].data = rawLogs[i].data;
+ logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
+ logs[i].topics = rawLogs[i].topics;
+ logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
+ logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
+ logs[i].removed = rawLogs[i].removed;
+ }
+ return logs;
+ }
+
+ // Deploy a contract by fetching the contract bytecode from
+ // the artifacts directory
+ // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`
+ function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) {
+ bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(0, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
+ }
+
+ function deployCode(string memory what) internal virtual returns (address addr) {
+ bytes memory bytecode = vm.getCode(what);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(0, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string): Deployment failed.");
+ }
+
+ /// @dev deploy contract with value on construction
+ function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) {
+ bytes memory bytecode = abi.encodePacked(vm.getCode(what), args);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(val, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
+ }
+
+ function deployCode(string memory what, uint256 val) internal virtual returns (address addr) {
+ bytes memory bytecode = vm.getCode(what);
+ /// @solidity memory-safe-assembly
+ assembly {
+ addr := create(val, add(bytecode, 0x20), mload(bytecode))
+ }
+
+ require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
+ }
+
+ // creates a labeled address and the corresponding private key
+ function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) {
+ privateKey = uint256(keccak256(abi.encodePacked(name)));
+ addr = vm.addr(privateKey);
+ vm.label(addr, name);
+ }
+
+ // creates a labeled address
+ function makeAddr(string memory name) internal virtual returns (address addr) {
+ (addr,) = makeAddrAndKey(name);
+ }
+
+ // Destroys an account immediately, sending the balance to beneficiary.
+ // Destroying means: balance will be zero, code will be empty, and nonce will be 0
+ // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce
+ // only after tx ends, this will run immediately.
+ function destroyAccount(address who, address beneficiary) internal virtual {
+ uint256 currBalance = who.balance;
+ vm.etch(who, abi.encode());
+ vm.deal(who, 0);
+ vm.resetNonce(who);
+
+ uint256 beneficiaryBalance = beneficiary.balance;
+ vm.deal(beneficiary, currBalance + beneficiaryBalance);
+ }
+
+ // creates a struct containing both a labeled address and the corresponding private key
+ function makeAccount(string memory name) internal virtual returns (Account memory account) {
+ (account.addr, account.key) = makeAddrAndKey(name);
+ }
+
+ function deriveRememberKey(string memory mnemonic, uint32 index)
+ internal
+ virtual
+ returns (address who, uint256 privateKey)
+ {
+ privateKey = vm.deriveKey(mnemonic, index);
+ who = vm.rememberKey(privateKey);
+ }
+
+ function _bytesToUint(bytes memory b) private pure returns (uint256) {
+ require(b.length <= 32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
+ return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
+ }
+
+ function isFork() internal view virtual returns (bool status) {
+ try vm.activeFork() {
+ status = true;
+ } catch (bytes memory) {}
+ }
+
+ modifier skipWhenForking() {
+ if (!isFork()) {
+ _;
+ }
+ }
+
+ modifier skipWhenNotForking() {
+ if (isFork()) {
+ _;
+ }
+ }
+
+ modifier noGasMetering() {
+ vm.pauseGasMetering();
+ // To prevent turning gas monitoring back on with nested functions that use this modifier,
+ // we check if gasMetering started in the off position. If it did, we don't want to turn
+ // it back on until we exit the top level function that used the modifier
+ //
+ // i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.
+ // funcA will have `gasStartedOff` as false, funcB will have it as true,
+ // so we only turn metering back on at the end of the funcA
+ bool gasStartedOff = gasMeteringOff;
+ gasMeteringOff = true;
+
+ _;
+
+ // if gas metering was on when this modifier was called, turn it back on at the end
+ if (!gasStartedOff) {
+ gasMeteringOff = false;
+ vm.resumeGasMetering();
+ }
+ }
+
+ // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
+ // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
+ // can't simply access the chain ID in a normal view or pure function because the solc View Pure
+ // Checker changed `chainid` from pure to view in 0.8.0.
+ function _viewChainId() private view returns (uint256 chainId) {
+ // Assembly required since `block.chainid` was introduced in 0.8.0.
+ assembly {
+ chainId := chainid()
+ }
+
+ address(this); // Silence warnings in older Solc versions.
+ }
+
+ function _pureChainId() private pure returns (uint256 chainId) {
+ function() internal view returns (uint256) fnIn = _viewChainId;
+ function() internal pure returns (uint256) pureChainId;
+ assembly {
+ pureChainId := fnIn
+ }
+ chainId = pureChainId();
+ }
+}
+
+// Wrappers around cheatcodes to avoid footguns
+abstract contract StdCheats is StdCheatsSafe {
+ using stdStorage for StdStorage;
+
+ StdStorage private stdstore;
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+ address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
+
+ // Skip forward or rewind time by the specified number of seconds
+ function skip(uint256 time) internal virtual {
+ vm.warp(block.timestamp + time);
+ }
+
+ function rewind(uint256 time) internal virtual {
+ vm.warp(block.timestamp - time);
+ }
+
+ // Setup a prank from an address that has some ether
+ function hoax(address msgSender) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.prank(msgSender);
+ }
+
+ function hoax(address msgSender, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.prank(msgSender);
+ }
+
+ function hoax(address msgSender, address origin) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.prank(msgSender, origin);
+ }
+
+ function hoax(address msgSender, address origin, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.prank(msgSender, origin);
+ }
+
+ // Start perpetual prank from an address that has some ether
+ function startHoax(address msgSender) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.startPrank(msgSender);
+ }
+
+ function startHoax(address msgSender, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.startPrank(msgSender);
+ }
+
+ // Start perpetual prank from an address that has some ether
+ // tx.origin is set to the origin parameter
+ function startHoax(address msgSender, address origin) internal virtual {
+ vm.deal(msgSender, 1 << 128);
+ vm.startPrank(msgSender, origin);
+ }
+
+ function startHoax(address msgSender, address origin, uint256 give) internal virtual {
+ vm.deal(msgSender, give);
+ vm.startPrank(msgSender, origin);
+ }
+
+ function changePrank(address msgSender) internal virtual {
+ console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
+ vm.stopPrank();
+ vm.startPrank(msgSender);
+ }
+
+ function changePrank(address msgSender, address txOrigin) internal virtual {
+ vm.stopPrank();
+ vm.startPrank(msgSender, txOrigin);
+ }
+
+ // The same as Vm's `deal`
+ // Use the alternative signature for ERC20 tokens
+ function deal(address to, uint256 give) internal virtual {
+ vm.deal(to, give);
+ }
+
+ // Set the balance of an account for any ERC20 token
+ // Use the alternative signature to update `totalSupply`
+ function deal(address token, address to, uint256 give) internal virtual {
+ deal(token, to, give, false);
+ }
+
+ // Set the balance of an account for any ERC1155 token
+ // Use the alternative signature to update `totalSupply`
+ function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual {
+ dealERC1155(token, to, id, give, false);
+ }
+
+ function deal(address token, address to, uint256 give, bool adjust) internal virtual {
+ // get current balance
+ (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
+ uint256 prevBal = abi.decode(balData, (uint256));
+
+ // update balance
+ stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
+
+ // update total supply
+ if (adjust) {
+ (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
+ uint256 totSup = abi.decode(totSupData, (uint256));
+ if (give < prevBal) {
+ totSup -= (prevBal - give);
+ } else {
+ totSup += (give - prevBal);
+ }
+ stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
+ }
+ }
+
+ function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual {
+ // get current balance
+ (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
+ uint256 prevBal = abi.decode(balData, (uint256));
+
+ // update balance
+ stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
+
+ // update total supply
+ if (adjust) {
+ (, bytes memory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
+ require(
+ totSupData.length != 0,
+ "StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
+ );
+ uint256 totSup = abi.decode(totSupData, (uint256));
+ if (give < prevBal) {
+ totSup -= (prevBal - give);
+ } else {
+ totSup += (give - prevBal);
+ }
+ stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
+ }
+ }
+
+ function dealERC721(address token, address to, uint256 id) internal virtual {
+ // check if token id is already minted and the actual owner.
+ (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
+ require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
+
+ // get owner current balance
+ (, bytes memory fromBalData) =
+ token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
+ uint256 fromPrevBal = abi.decode(fromBalData, (uint256));
+
+ // get new user current balance
+ (, bytes memory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
+ uint256 toPrevBal = abi.decode(toBalData, (uint256));
+
+ // update balances
+ stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
+ stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
+
+ // update owner
+ stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
+ }
+
+ function deployCodeTo(string memory what, address where) internal virtual {
+ deployCodeTo(what, "", 0, where);
+ }
+
+ function deployCodeTo(string memory what, bytes memory args, address where) internal virtual {
+ deployCodeTo(what, args, 0, where);
+ }
+
+ function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual {
+ bytes memory creationCode = vm.getCode(what);
+ vm.etch(where, abi.encodePacked(creationCode, args));
+ (bool success, bytes memory runtimeBytecode) = where.call{value: value}("");
+ require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
+ vm.etch(where, runtimeBytecode);
+ }
+
+ // Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.
+ function console2_log_StdCheats(string memory p0) private view {
+ (bool status,) = address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
+ status;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdError.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdError.sol
new file mode 100644
index 000000000..a302191fa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdError.sol
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: MIT
+// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test
+pragma solidity >=0.6.2 <0.9.0;
+
+library stdError {
+ bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01);
+ bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11);
+ bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12);
+ bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21);
+ bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22);
+ bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31);
+ bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32);
+ bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41);
+ bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdInvariant.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdInvariant.sol
new file mode 100644
index 000000000..056db98fc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdInvariant.sol
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+abstract contract StdInvariant {
+ struct FuzzSelector {
+ address addr;
+ bytes4[] selectors;
+ }
+
+ struct FuzzArtifactSelector {
+ string artifact;
+ bytes4[] selectors;
+ }
+
+ struct FuzzInterface {
+ address addr;
+ string[] artifacts;
+ }
+
+ address[] private _excludedContracts;
+ address[] private _excludedSenders;
+ address[] private _targetedContracts;
+ address[] private _targetedSenders;
+
+ string[] private _excludedArtifacts;
+ string[] private _targetedArtifacts;
+
+ FuzzArtifactSelector[] private _targetedArtifactSelectors;
+
+ FuzzSelector[] private _excludedSelectors;
+ FuzzSelector[] private _targetedSelectors;
+
+ FuzzInterface[] private _targetedInterfaces;
+
+ // Functions for users:
+ // These are intended to be called in tests.
+
+ function excludeContract(address newExcludedContract_) internal {
+ _excludedContracts.push(newExcludedContract_);
+ }
+
+ function excludeSelector(FuzzSelector memory newExcludedSelector_) internal {
+ _excludedSelectors.push(newExcludedSelector_);
+ }
+
+ function excludeSender(address newExcludedSender_) internal {
+ _excludedSenders.push(newExcludedSender_);
+ }
+
+ function excludeArtifact(string memory newExcludedArtifact_) internal {
+ _excludedArtifacts.push(newExcludedArtifact_);
+ }
+
+ function targetArtifact(string memory newTargetedArtifact_) internal {
+ _targetedArtifacts.push(newTargetedArtifact_);
+ }
+
+ function targetArtifactSelector(FuzzArtifactSelector memory newTargetedArtifactSelector_) internal {
+ _targetedArtifactSelectors.push(newTargetedArtifactSelector_);
+ }
+
+ function targetContract(address newTargetedContract_) internal {
+ _targetedContracts.push(newTargetedContract_);
+ }
+
+ function targetSelector(FuzzSelector memory newTargetedSelector_) internal {
+ _targetedSelectors.push(newTargetedSelector_);
+ }
+
+ function targetSender(address newTargetedSender_) internal {
+ _targetedSenders.push(newTargetedSender_);
+ }
+
+ function targetInterface(FuzzInterface memory newTargetedInterface_) internal {
+ _targetedInterfaces.push(newTargetedInterface_);
+ }
+
+ // Functions for forge:
+ // These are called by forge to run invariant tests and don't need to be called in tests.
+
+ function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) {
+ excludedArtifacts_ = _excludedArtifacts;
+ }
+
+ function excludeContracts() public view returns (address[] memory excludedContracts_) {
+ excludedContracts_ = _excludedContracts;
+ }
+
+ function excludeSelectors() public view returns (FuzzSelector[] memory excludedSelectors_) {
+ excludedSelectors_ = _excludedSelectors;
+ }
+
+ function excludeSenders() public view returns (address[] memory excludedSenders_) {
+ excludedSenders_ = _excludedSenders;
+ }
+
+ function targetArtifacts() public view returns (string[] memory targetedArtifacts_) {
+ targetedArtifacts_ = _targetedArtifacts;
+ }
+
+ function targetArtifactSelectors() public view returns (FuzzArtifactSelector[] memory targetedArtifactSelectors_) {
+ targetedArtifactSelectors_ = _targetedArtifactSelectors;
+ }
+
+ function targetContracts() public view returns (address[] memory targetedContracts_) {
+ targetedContracts_ = _targetedContracts;
+ }
+
+ function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) {
+ targetedSelectors_ = _targetedSelectors;
+ }
+
+ function targetSenders() public view returns (address[] memory targetedSenders_) {
+ targetedSenders_ = _targetedSenders;
+ }
+
+ function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) {
+ targetedInterfaces_ = _targetedInterfaces;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdJson.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdJson.sol
new file mode 100644
index 000000000..2a033c03a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdJson.sol
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.0 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {VmSafe} from "./Vm.sol";
+
+// Helpers for parsing and writing JSON files
+// To parse:
+// ```
+// using stdJson for string;
+// string memory json = vm.readFile("");
+// json.readUint("");
+// ```
+// To write:
+// ```
+// using stdJson for string;
+// string memory json = "json";
+// json.serialize("a", uint256(123));
+// string memory semiFinal = json.serialize("b", string("test"));
+// string memory finalJson = json.serialize("c", semiFinal);
+// finalJson.write("");
+// ```
+
+library stdJson {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function keyExists(string memory json, string memory key) internal view returns (bool) {
+ return vm.keyExistsJson(json, key);
+ }
+
+ function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) {
+ return vm.parseJson(json, key);
+ }
+
+ function readUint(string memory json, string memory key) internal pure returns (uint256) {
+ return vm.parseJsonUint(json, key);
+ }
+
+ function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) {
+ return vm.parseJsonUintArray(json, key);
+ }
+
+ function readInt(string memory json, string memory key) internal pure returns (int256) {
+ return vm.parseJsonInt(json, key);
+ }
+
+ function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) {
+ return vm.parseJsonIntArray(json, key);
+ }
+
+ function readBytes32(string memory json, string memory key) internal pure returns (bytes32) {
+ return vm.parseJsonBytes32(json, key);
+ }
+
+ function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) {
+ return vm.parseJsonBytes32Array(json, key);
+ }
+
+ function readString(string memory json, string memory key) internal pure returns (string memory) {
+ return vm.parseJsonString(json, key);
+ }
+
+ function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) {
+ return vm.parseJsonStringArray(json, key);
+ }
+
+ function readAddress(string memory json, string memory key) internal pure returns (address) {
+ return vm.parseJsonAddress(json, key);
+ }
+
+ function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) {
+ return vm.parseJsonAddressArray(json, key);
+ }
+
+ function readBool(string memory json, string memory key) internal pure returns (bool) {
+ return vm.parseJsonBool(json, key);
+ }
+
+ function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) {
+ return vm.parseJsonBoolArray(json, key);
+ }
+
+ function readBytes(string memory json, string memory key) internal pure returns (bytes memory) {
+ return vm.parseJsonBytes(json, key);
+ }
+
+ function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) {
+ return vm.parseJsonBytesArray(json, key);
+ }
+
+ function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) {
+ return keyExists(json, key) ? readUint(json, key) : defaultValue;
+ }
+
+ function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue)
+ internal
+ view
+ returns (uint256[] memory)
+ {
+ return keyExists(json, key) ? readUintArray(json, key) : defaultValue;
+ }
+
+ function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) {
+ return keyExists(json, key) ? readInt(json, key) : defaultValue;
+ }
+
+ function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue)
+ internal
+ view
+ returns (int256[] memory)
+ {
+ return keyExists(json, key) ? readIntArray(json, key) : defaultValue;
+ }
+
+ function readBytes32Or(string memory json, string memory key, bytes32 defaultValue)
+ internal
+ view
+ returns (bytes32)
+ {
+ return keyExists(json, key) ? readBytes32(json, key) : defaultValue;
+ }
+
+ function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue)
+ internal
+ view
+ returns (bytes32[] memory)
+ {
+ return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue;
+ }
+
+ function readStringOr(string memory json, string memory key, string memory defaultValue)
+ internal
+ view
+ returns (string memory)
+ {
+ return keyExists(json, key) ? readString(json, key) : defaultValue;
+ }
+
+ function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue)
+ internal
+ view
+ returns (string[] memory)
+ {
+ return keyExists(json, key) ? readStringArray(json, key) : defaultValue;
+ }
+
+ function readAddressOr(string memory json, string memory key, address defaultValue)
+ internal
+ view
+ returns (address)
+ {
+ return keyExists(json, key) ? readAddress(json, key) : defaultValue;
+ }
+
+ function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue)
+ internal
+ view
+ returns (address[] memory)
+ {
+ return keyExists(json, key) ? readAddressArray(json, key) : defaultValue;
+ }
+
+ function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) {
+ return keyExists(json, key) ? readBool(json, key) : defaultValue;
+ }
+
+ function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue)
+ internal
+ view
+ returns (bool[] memory)
+ {
+ return keyExists(json, key) ? readBoolArray(json, key) : defaultValue;
+ }
+
+ function readBytesOr(string memory json, string memory key, bytes memory defaultValue)
+ internal
+ view
+ returns (bytes memory)
+ {
+ return keyExists(json, key) ? readBytes(json, key) : defaultValue;
+ }
+
+ function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue)
+ internal
+ view
+ returns (bytes[] memory)
+ {
+ return keyExists(json, key) ? readBytesArray(json, key) : defaultValue;
+ }
+
+ function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
+ return vm.serializeJson(jsonKey, rootObject);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function write(string memory jsonKey, string memory path) internal {
+ vm.writeJson(jsonKey, path);
+ }
+
+ function write(string memory jsonKey, string memory path, string memory valueKey) internal {
+ vm.writeJson(jsonKey, path, valueKey);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdMath.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdMath.sol
new file mode 100644
index 000000000..459523bda
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdMath.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+library stdMath {
+ int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968;
+
+ function abs(int256 a) internal pure returns (uint256) {
+ // Required or it will fail when `a = type(int256).min`
+ if (a == INT256_MIN) {
+ return 57896044618658097711785492504343953926634992332820282019728792003956564819968;
+ }
+
+ return uint256(a > 0 ? a : -a);
+ }
+
+ function delta(uint256 a, uint256 b) internal pure returns (uint256) {
+ return a > b ? a - b : b - a;
+ }
+
+ function delta(int256 a, int256 b) internal pure returns (uint256) {
+ // a and b are of the same sign
+ // this works thanks to two's complement, the left-most bit is the sign bit
+ if ((a ^ b) > -1) {
+ return delta(abs(a), abs(b));
+ }
+
+ // a and b are of opposite signs
+ return abs(a) + abs(b);
+ }
+
+ function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) {
+ uint256 absDelta = delta(a, b);
+
+ return absDelta * 1e18 / b;
+ }
+
+ function percentDelta(int256 a, int256 b) internal pure returns (uint256) {
+ uint256 absDelta = delta(a, b);
+ uint256 absB = abs(b);
+
+ return absDelta * 1e18 / absB;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdStorage.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdStorage.sol
new file mode 100644
index 000000000..bf3223dee
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdStorage.sol
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {Vm} from "./Vm.sol";
+
+struct FindData {
+ uint256 slot;
+ uint256 offsetLeft;
+ uint256 offsetRight;
+ bool found;
+}
+
+struct StdStorage {
+ mapping(address => mapping(bytes4 => mapping(bytes32 => FindData))) finds;
+ bytes32[] _keys;
+ bytes4 _sig;
+ uint256 _depth;
+ address _target;
+ bytes32 _set;
+ bool _enable_packed_slots;
+ bytes _calldata;
+}
+
+library stdStorageSafe {
+ event SlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
+ event WARNING_UninitedSlot(address who, uint256 slot);
+
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+ uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ function sigs(string memory sigStr) internal pure returns (bytes4) {
+ return bytes4(keccak256(bytes(sigStr)));
+ }
+
+ function getCallParams(StdStorage storage self) internal view returns (bytes memory) {
+ if (self._calldata.length == 0) {
+ return flatten(self._keys);
+ } else {
+ return self._calldata;
+ }
+ }
+
+ // Calls target contract with configured parameters
+ function callTarget(StdStorage storage self) internal view returns (bool, bytes32) {
+ bytes memory cald = abi.encodePacked(self._sig, getCallParams(self));
+ (bool success, bytes memory rdat) = self._target.staticcall(cald);
+ bytes32 result = bytesToBytes32(rdat, 32 * self._depth);
+
+ return (success, result);
+ }
+
+ // Tries mutating slot value to determine if the targeted value is stored in it.
+ // If current value is 0, then we are setting slot value to type(uint256).max
+ // Otherwise, we set it to 0. That way, return value should always be affected.
+ function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) {
+ bytes32 prevSlotValue = vm.load(self._target, slot);
+ (bool success, bytes32 prevReturnValue) = callTarget(self);
+
+ bytes32 testVal = prevReturnValue == bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0);
+ vm.store(self._target, slot, testVal);
+
+ (, bytes32 newReturnValue) = callTarget(self);
+
+ vm.store(self._target, slot, prevSlotValue);
+
+ return (success && (prevReturnValue != newReturnValue));
+ }
+
+ // Tries setting one of the bits in slot to 1 until return value changes.
+ // Index of resulted bit is an offset packed slot has from left/right side
+ function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) {
+ for (uint256 offset = 0; offset < 256; offset++) {
+ uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset);
+ vm.store(self._target, slot, bytes32(valueToPut));
+
+ (bool success, bytes32 data) = callTarget(self);
+
+ if (success && (uint256(data) > 0)) {
+ return (true, offset);
+ }
+ }
+ return (false, 0);
+ }
+
+ function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) {
+ bytes32 prevSlotValue = vm.load(self._target, slot);
+
+ (bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true);
+ (bool foundRight, uint256 offsetRight) = findOffset(self, slot, false);
+
+ // `findOffset` may mutate slot value, so we are setting it to initial value
+ vm.store(self._target, slot, prevSlotValue);
+ return (foundLeft && foundRight, offsetLeft, offsetRight);
+ }
+
+ function find(StdStorage storage self) internal returns (FindData storage) {
+ return find(self, true);
+ }
+
+ /// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against
+ // slot complexity:
+ // if flat, will be bytes32(uint256(uint));
+ // if map, will be keccak256(abi.encode(key, uint(slot)));
+ // if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));
+ // if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);
+ function find(StdStorage storage self, bool _clear) internal returns (FindData storage) {
+ address who = self._target;
+ bytes4 fsig = self._sig;
+ uint256 field_depth = self._depth;
+ bytes memory params = getCallParams(self);
+
+ // calldata to test against
+ if (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
+ if (_clear) {
+ clear(self);
+ }
+ return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
+ }
+ vm.record();
+ (, bytes32 callResult) = callTarget(self);
+ (bytes32[] memory reads,) = vm.accesses(address(who));
+
+ if (reads.length == 0) {
+ revert("stdStorage find(StdStorage): No storage use detected for target.");
+ } else {
+ for (uint256 i = reads.length; --i >= 0;) {
+ bytes32 prev = vm.load(who, reads[i]);
+ if (prev == bytes32(0)) {
+ emit WARNING_UninitedSlot(who, uint256(reads[i]));
+ }
+
+ if (!checkSlotMutatesCall(self, reads[i])) {
+ continue;
+ }
+
+ (uint256 offsetLeft, uint256 offsetRight) = (0, 0);
+
+ if (self._enable_packed_slots) {
+ bool found;
+ (found, offsetLeft, offsetRight) = findOffsets(self, reads[i]);
+ if (!found) {
+ continue;
+ }
+ }
+
+ // Check that value between found offsets is equal to the current call result
+ uint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight;
+
+ if (uint256(callResult) != curVal) {
+ continue;
+ }
+
+ emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i]));
+ self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] =
+ FindData(uint256(reads[i]), offsetLeft, offsetRight, true);
+ break;
+ }
+ }
+
+ require(
+ self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found,
+ "stdStorage find(StdStorage): Slot(s) not found."
+ );
+
+ if (_clear) {
+ clear(self);
+ }
+ return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
+ }
+
+ function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
+ self._target = _target;
+ return self;
+ }
+
+ function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
+ self._sig = _sig;
+ return self;
+ }
+
+ function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
+ self._sig = sigs(_sig);
+ return self;
+ }
+
+ function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
+ self._calldata = _calldata;
+ return self;
+ }
+
+ function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
+ self._keys.push(bytes32(uint256(uint160(who))));
+ return self;
+ }
+
+ function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
+ self._keys.push(bytes32(amt));
+ return self;
+ }
+
+ function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
+ self._keys.push(key);
+ return self;
+ }
+
+ function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
+ self._enable_packed_slots = true;
+ return self;
+ }
+
+ function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
+ self._depth = _depth;
+ return self;
+ }
+
+ function read(StdStorage storage self) private returns (bytes memory) {
+ FindData storage data = find(self, false);
+ uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight);
+ uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight;
+ clear(self);
+ return abi.encode(value);
+ }
+
+ function read_bytes32(StdStorage storage self) internal returns (bytes32) {
+ return abi.decode(read(self), (bytes32));
+ }
+
+ function read_bool(StdStorage storage self) internal returns (bool) {
+ int256 v = read_int(self);
+ if (v == 0) return false;
+ if (v == 1) return true;
+ revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
+ }
+
+ function read_address(StdStorage storage self) internal returns (address) {
+ return abi.decode(read(self), (address));
+ }
+
+ function read_uint(StdStorage storage self) internal returns (uint256) {
+ return abi.decode(read(self), (uint256));
+ }
+
+ function read_int(StdStorage storage self) internal returns (int256) {
+ return abi.decode(read(self), (int256));
+ }
+
+ function parent(StdStorage storage self) internal returns (uint256, bytes32) {
+ address who = self._target;
+ uint256 field_depth = self._depth;
+ vm.startMappingRecording();
+ uint256 child = find(self, true).slot - field_depth;
+ (bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
+ if (!found) {
+ revert(
+ "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
+ );
+ }
+ return (uint256(parent_slot), key);
+ }
+
+ function root(StdStorage storage self) internal returns (uint256) {
+ address who = self._target;
+ uint256 field_depth = self._depth;
+ vm.startMappingRecording();
+ uint256 child = find(self, true).slot - field_depth;
+ bool found;
+ bytes32 root_slot;
+ bytes32 parent_slot;
+ (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
+ if (!found) {
+ revert(
+ "stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
+ );
+ }
+ while (found) {
+ root_slot = parent_slot;
+ (found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
+ }
+ return uint256(root_slot);
+ }
+
+ function bytesToBytes32(bytes memory b, uint256 offset) private pure returns (bytes32) {
+ bytes32 out;
+
+ uint256 max = b.length > 32 ? 32 : b.length;
+ for (uint256 i = 0; i < max; i++) {
+ out |= bytes32(b[offset + i] & 0xFF) >> (i * 8);
+ }
+ return out;
+ }
+
+ function flatten(bytes32[] memory b) private pure returns (bytes memory) {
+ bytes memory result = new bytes(b.length * 32);
+ for (uint256 i = 0; i < b.length; i++) {
+ bytes32 k = b[i];
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(add(result, add(32, mul(32, i))), k)
+ }
+ }
+
+ return result;
+ }
+
+ function clear(StdStorage storage self) internal {
+ delete self._target;
+ delete self._sig;
+ delete self._keys;
+ delete self._depth;
+ delete self._enable_packed_slots;
+ delete self._calldata;
+ }
+
+ // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight`
+ // (slotValue & mask) >> offsetRight will be the value of the given packed variable
+ function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) {
+ // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight;
+ // using assembly because (1 << 256) causes overflow
+ assembly {
+ mask := shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1))
+ }
+ }
+
+ // Returns slot value with updated packed variable.
+ function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight)
+ internal
+ pure
+ returns (bytes32 newValue)
+ {
+ return bytes32((uint256(curValue) & ~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight));
+ }
+}
+
+library stdStorage {
+ Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function sigs(string memory sigStr) internal pure returns (bytes4) {
+ return stdStorageSafe.sigs(sigStr);
+ }
+
+ function find(StdStorage storage self) internal returns (uint256) {
+ return find(self, true);
+ }
+
+ function find(StdStorage storage self, bool _clear) internal returns (uint256) {
+ return stdStorageSafe.find(self, _clear).slot;
+ }
+
+ function target(StdStorage storage self, address _target) internal returns (StdStorage storage) {
+ return stdStorageSafe.target(self, _target);
+ }
+
+ function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) {
+ return stdStorageSafe.sig(self, _sig);
+ }
+
+ function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) {
+ return stdStorageSafe.sig(self, _sig);
+ }
+
+ function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_key(self, who);
+ }
+
+ function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_key(self, amt);
+ }
+
+ function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_key(self, key);
+ }
+
+ function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) {
+ return stdStorageSafe.with_calldata(self, _calldata);
+ }
+
+ function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) {
+ return stdStorageSafe.enable_packed_slots(self);
+ }
+
+ function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) {
+ return stdStorageSafe.depth(self, _depth);
+ }
+
+ function clear(StdStorage storage self) internal {
+ stdStorageSafe.clear(self);
+ }
+
+ function checked_write(StdStorage storage self, address who) internal {
+ checked_write(self, bytes32(uint256(uint160(who))));
+ }
+
+ function checked_write(StdStorage storage self, uint256 amt) internal {
+ checked_write(self, bytes32(amt));
+ }
+
+ function checked_write_int(StdStorage storage self, int256 val) internal {
+ checked_write(self, bytes32(uint256(val)));
+ }
+
+ function checked_write(StdStorage storage self, bool write) internal {
+ bytes32 t;
+ /// @solidity memory-safe-assembly
+ assembly {
+ t := write
+ }
+ checked_write(self, t);
+ }
+
+ function checked_write(StdStorage storage self, bytes32 set) internal {
+ address who = self._target;
+ bytes4 fsig = self._sig;
+ uint256 field_depth = self._depth;
+ bytes memory params = stdStorageSafe.getCallParams(self);
+
+ if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
+ find(self, false);
+ }
+ FindData storage data = self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
+ if ((data.offsetLeft + data.offsetRight) > 0) {
+ uint256 maxVal = 2 ** (256 - (data.offsetLeft + data.offsetRight));
+ require(
+ uint256(set) < maxVal,
+ string(
+ abi.encodePacked(
+ "stdStorage find(StdStorage): Packed slot. We can't fit value greater than ",
+ vm.toString(maxVal)
+ )
+ )
+ );
+ }
+ bytes32 curVal = vm.load(who, bytes32(data.slot));
+ bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight);
+
+ vm.store(who, bytes32(data.slot), valToSet);
+
+ (bool success, bytes32 callResult) = stdStorageSafe.callTarget(self);
+
+ if (!success || callResult != set) {
+ vm.store(who, bytes32(data.slot), curVal);
+ revert("stdStorage find(StdStorage): Failed to write value.");
+ }
+ clear(self);
+ }
+
+ function read_bytes32(StdStorage storage self) internal returns (bytes32) {
+ return stdStorageSafe.read_bytes32(self);
+ }
+
+ function read_bool(StdStorage storage self) internal returns (bool) {
+ return stdStorageSafe.read_bool(self);
+ }
+
+ function read_address(StdStorage storage self) internal returns (address) {
+ return stdStorageSafe.read_address(self);
+ }
+
+ function read_uint(StdStorage storage self) internal returns (uint256) {
+ return stdStorageSafe.read_uint(self);
+ }
+
+ function read_int(StdStorage storage self) internal returns (int256) {
+ return stdStorageSafe.read_int(self);
+ }
+
+ function parent(StdStorage storage self) internal returns (uint256, bytes32) {
+ return stdStorageSafe.parent(self);
+ }
+
+ function root(StdStorage storage self) internal returns (uint256) {
+ return stdStorageSafe.root(self);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdStyle.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdStyle.sol
new file mode 100644
index 000000000..d371e0c60
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdStyle.sol
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.4.22 <0.9.0;
+
+import {VmSafe} from "./Vm.sol";
+
+library StdStyle {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ string constant RED = "\u001b[91m";
+ string constant GREEN = "\u001b[92m";
+ string constant YELLOW = "\u001b[93m";
+ string constant BLUE = "\u001b[94m";
+ string constant MAGENTA = "\u001b[95m";
+ string constant CYAN = "\u001b[96m";
+ string constant BOLD = "\u001b[1m";
+ string constant DIM = "\u001b[2m";
+ string constant ITALIC = "\u001b[3m";
+ string constant UNDERLINE = "\u001b[4m";
+ string constant INVERSE = "\u001b[7m";
+ string constant RESET = "\u001b[0m";
+
+ function styleConcat(string memory style, string memory self) private pure returns (string memory) {
+ return string(abi.encodePacked(style, self, RESET));
+ }
+
+ function red(string memory self) internal pure returns (string memory) {
+ return styleConcat(RED, self);
+ }
+
+ function red(uint256 self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function red(int256 self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function red(address self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function red(bool self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function redBytes(bytes memory self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function redBytes32(bytes32 self) internal pure returns (string memory) {
+ return red(vm.toString(self));
+ }
+
+ function green(string memory self) internal pure returns (string memory) {
+ return styleConcat(GREEN, self);
+ }
+
+ function green(uint256 self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function green(int256 self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function green(address self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function green(bool self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function greenBytes(bytes memory self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function greenBytes32(bytes32 self) internal pure returns (string memory) {
+ return green(vm.toString(self));
+ }
+
+ function yellow(string memory self) internal pure returns (string memory) {
+ return styleConcat(YELLOW, self);
+ }
+
+ function yellow(uint256 self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellow(int256 self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellow(address self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellow(bool self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellowBytes(bytes memory self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function yellowBytes32(bytes32 self) internal pure returns (string memory) {
+ return yellow(vm.toString(self));
+ }
+
+ function blue(string memory self) internal pure returns (string memory) {
+ return styleConcat(BLUE, self);
+ }
+
+ function blue(uint256 self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blue(int256 self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blue(address self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blue(bool self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blueBytes(bytes memory self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function blueBytes32(bytes32 self) internal pure returns (string memory) {
+ return blue(vm.toString(self));
+ }
+
+ function magenta(string memory self) internal pure returns (string memory) {
+ return styleConcat(MAGENTA, self);
+ }
+
+ function magenta(uint256 self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magenta(int256 self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magenta(address self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magenta(bool self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magentaBytes(bytes memory self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function magentaBytes32(bytes32 self) internal pure returns (string memory) {
+ return magenta(vm.toString(self));
+ }
+
+ function cyan(string memory self) internal pure returns (string memory) {
+ return styleConcat(CYAN, self);
+ }
+
+ function cyan(uint256 self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyan(int256 self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyan(address self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyan(bool self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyanBytes(bytes memory self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function cyanBytes32(bytes32 self) internal pure returns (string memory) {
+ return cyan(vm.toString(self));
+ }
+
+ function bold(string memory self) internal pure returns (string memory) {
+ return styleConcat(BOLD, self);
+ }
+
+ function bold(uint256 self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function bold(int256 self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function bold(address self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function bold(bool self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function boldBytes(bytes memory self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function boldBytes32(bytes32 self) internal pure returns (string memory) {
+ return bold(vm.toString(self));
+ }
+
+ function dim(string memory self) internal pure returns (string memory) {
+ return styleConcat(DIM, self);
+ }
+
+ function dim(uint256 self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dim(int256 self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dim(address self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dim(bool self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dimBytes(bytes memory self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function dimBytes32(bytes32 self) internal pure returns (string memory) {
+ return dim(vm.toString(self));
+ }
+
+ function italic(string memory self) internal pure returns (string memory) {
+ return styleConcat(ITALIC, self);
+ }
+
+ function italic(uint256 self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italic(int256 self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italic(address self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italic(bool self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italicBytes(bytes memory self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function italicBytes32(bytes32 self) internal pure returns (string memory) {
+ return italic(vm.toString(self));
+ }
+
+ function underline(string memory self) internal pure returns (string memory) {
+ return styleConcat(UNDERLINE, self);
+ }
+
+ function underline(uint256 self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underline(int256 self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underline(address self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underline(bool self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underlineBytes(bytes memory self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function underlineBytes32(bytes32 self) internal pure returns (string memory) {
+ return underline(vm.toString(self));
+ }
+
+ function inverse(string memory self) internal pure returns (string memory) {
+ return styleConcat(INVERSE, self);
+ }
+
+ function inverse(uint256 self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverse(int256 self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverse(address self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverse(bool self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverseBytes(bytes memory self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+
+ function inverseBytes32(bytes32 self) internal pure returns (string memory) {
+ return inverse(vm.toString(self));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdToml.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdToml.sol
new file mode 100644
index 000000000..7ad3be2f9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdToml.sol
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.0 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {VmSafe} from "./Vm.sol";
+
+// Helpers for parsing and writing TOML files
+// To parse:
+// ```
+// using stdToml for string;
+// string memory toml = vm.readFile("");
+// toml.readUint("");
+// ```
+// To write:
+// ```
+// using stdToml for string;
+// string memory json = "json";
+// json.serialize("a", uint256(123));
+// string memory semiFinal = json.serialize("b", string("test"));
+// string memory finalJson = json.serialize("c", semiFinal);
+// finalJson.write("");
+// ```
+
+library stdToml {
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function keyExists(string memory toml, string memory key) internal view returns (bool) {
+ return vm.keyExistsToml(toml, key);
+ }
+
+ function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) {
+ return vm.parseToml(toml, key);
+ }
+
+ function readUint(string memory toml, string memory key) internal pure returns (uint256) {
+ return vm.parseTomlUint(toml, key);
+ }
+
+ function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) {
+ return vm.parseTomlUintArray(toml, key);
+ }
+
+ function readInt(string memory toml, string memory key) internal pure returns (int256) {
+ return vm.parseTomlInt(toml, key);
+ }
+
+ function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) {
+ return vm.parseTomlIntArray(toml, key);
+ }
+
+ function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) {
+ return vm.parseTomlBytes32(toml, key);
+ }
+
+ function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) {
+ return vm.parseTomlBytes32Array(toml, key);
+ }
+
+ function readString(string memory toml, string memory key) internal pure returns (string memory) {
+ return vm.parseTomlString(toml, key);
+ }
+
+ function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) {
+ return vm.parseTomlStringArray(toml, key);
+ }
+
+ function readAddress(string memory toml, string memory key) internal pure returns (address) {
+ return vm.parseTomlAddress(toml, key);
+ }
+
+ function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) {
+ return vm.parseTomlAddressArray(toml, key);
+ }
+
+ function readBool(string memory toml, string memory key) internal pure returns (bool) {
+ return vm.parseTomlBool(toml, key);
+ }
+
+ function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) {
+ return vm.parseTomlBoolArray(toml, key);
+ }
+
+ function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) {
+ return vm.parseTomlBytes(toml, key);
+ }
+
+ function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) {
+ return vm.parseTomlBytesArray(toml, key);
+ }
+
+ function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) {
+ return keyExists(toml, key) ? readUint(toml, key) : defaultValue;
+ }
+
+ function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue)
+ internal
+ view
+ returns (uint256[] memory)
+ {
+ return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue;
+ }
+
+ function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) {
+ return keyExists(toml, key) ? readInt(toml, key) : defaultValue;
+ }
+
+ function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue)
+ internal
+ view
+ returns (int256[] memory)
+ {
+ return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue;
+ }
+
+ function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue)
+ internal
+ view
+ returns (bytes32)
+ {
+ return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue;
+ }
+
+ function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue)
+ internal
+ view
+ returns (bytes32[] memory)
+ {
+ return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue;
+ }
+
+ function readStringOr(string memory toml, string memory key, string memory defaultValue)
+ internal
+ view
+ returns (string memory)
+ {
+ return keyExists(toml, key) ? readString(toml, key) : defaultValue;
+ }
+
+ function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue)
+ internal
+ view
+ returns (string[] memory)
+ {
+ return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue;
+ }
+
+ function readAddressOr(string memory toml, string memory key, address defaultValue)
+ internal
+ view
+ returns (address)
+ {
+ return keyExists(toml, key) ? readAddress(toml, key) : defaultValue;
+ }
+
+ function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue)
+ internal
+ view
+ returns (address[] memory)
+ {
+ return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue;
+ }
+
+ function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) {
+ return keyExists(toml, key) ? readBool(toml, key) : defaultValue;
+ }
+
+ function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue)
+ internal
+ view
+ returns (bool[] memory)
+ {
+ return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue;
+ }
+
+ function readBytesOr(string memory toml, string memory key, bytes memory defaultValue)
+ internal
+ view
+ returns (bytes memory)
+ {
+ return keyExists(toml, key) ? readBytes(toml, key) : defaultValue;
+ }
+
+ function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue)
+ internal
+ view
+ returns (bytes[] memory)
+ {
+ return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue;
+ }
+
+ function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) {
+ return vm.serializeJson(jsonKey, rootObject);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bool[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBool(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, uint256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeUint(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, int256[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeInt(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, address[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeAddress(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes32[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes32(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, bytes[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeBytes(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function serialize(string memory jsonKey, string memory key, string[] memory value)
+ internal
+ returns (string memory)
+ {
+ return vm.serializeString(jsonKey, key, value);
+ }
+
+ function write(string memory jsonKey, string memory path) internal {
+ vm.writeToml(jsonKey, path);
+ }
+
+ function write(string memory jsonKey, string memory path, string memory valueKey) internal {
+ vm.writeToml(jsonKey, path, valueKey);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdUtils.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdUtils.sol
new file mode 100644
index 000000000..5d120439f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/StdUtils.sol
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import {IMulticall3} from "./interfaces/IMulticall3.sol";
+import {MockERC20} from "./mocks/MockERC20.sol";
+import {MockERC721} from "./mocks/MockERC721.sol";
+import {VmSafe} from "./Vm.sol";
+
+abstract contract StdUtils {
+ /*//////////////////////////////////////////////////////////////////////////
+ CONSTANTS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
+ VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
+ address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67;
+ uint256 private constant INT256_MIN_ABS =
+ 57896044618658097711785492504343953926634992332820282019728792003956564819968;
+ uint256 private constant SECP256K1_ORDER =
+ 115792089237316195423570985008687907852837564279074904382605163141518161494337;
+ uint256 private constant UINT256_MAX =
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935;
+
+ // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.
+ address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
+
+ /*//////////////////////////////////////////////////////////////////////////
+ INTERNAL FUNCTIONS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
+ require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
+ // If x is between min and max, return x directly. This is to ensure that dictionary values
+ // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188
+ if (x >= min && x <= max) return x;
+
+ uint256 size = max - min + 1;
+
+ // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.
+ // This helps ensure coverage of the min/max values.
+ if (x <= 3 && size > x) return min + x;
+ if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x);
+
+ // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
+ if (x > max) {
+ uint256 diff = x - max;
+ uint256 rem = diff % size;
+ if (rem == 0) return max;
+ result = min + rem - 1;
+ } else if (x < min) {
+ uint256 diff = min - x;
+ uint256 rem = diff % size;
+ if (rem == 0) return min;
+ result = max - rem + 1;
+ }
+ }
+
+ function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) {
+ result = _bound(x, min, max);
+ console2_log_StdUtils("Bound result", result);
+ }
+
+ function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
+ require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
+
+ // Shifting all int256 values to uint256 to use _bound function. The range of two types are:
+ // int256 : -(2**255) ~ (2**255 - 1)
+ // uint256: 0 ~ (2**256 - 1)
+ // So, add 2**255, INT256_MIN_ABS to the integer values.
+ //
+ // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.
+ // So, use `~uint256(x) + 1` instead.
+ uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS);
+ uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS);
+ uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS);
+
+ uint256 y = _bound(_x, _min, _max);
+
+ // To move it back to int256 value, subtract INT256_MIN_ABS at here.
+ result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS);
+ }
+
+ function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) {
+ result = _bound(x, min, max);
+ console2_log_StdUtils("Bound result", vm.toString(result));
+ }
+
+ function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) {
+ result = _bound(privateKey, 1, SECP256K1_ORDER - 1);
+ }
+
+ function bytesToUint(bytes memory b) internal pure virtual returns (uint256) {
+ require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
+ return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256));
+ }
+
+ /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce
+ /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)
+ function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) {
+ console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
+ return vm.computeCreateAddress(deployer, nonce);
+ }
+
+ function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
+ internal
+ pure
+ virtual
+ returns (address)
+ {
+ console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
+ return vm.computeCreate2Address(salt, initcodeHash, deployer);
+ }
+
+ /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer
+ function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) {
+ console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
+ return vm.computeCreate2Address(salt, initCodeHash);
+ }
+
+ /// @dev returns an initialized mock ERC20 contract
+ function deployMockERC20(string memory name, string memory symbol, uint8 decimals)
+ internal
+ returns (MockERC20 mock)
+ {
+ mock = new MockERC20();
+ mock.initialize(name, symbol, decimals);
+ }
+
+ /// @dev returns an initialized mock ERC721 contract
+ function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) {
+ mock = new MockERC721();
+ mock.initialize(name, symbol);
+ }
+
+ /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments
+ /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
+ function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) {
+ return hashInitCode(creationCode, "");
+ }
+
+ /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2
+ /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode
+ /// @param args the ABI-encoded arguments to the constructor of C
+ function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(creationCode, args));
+ }
+
+ // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.
+ function getTokenBalances(address token, address[] memory addresses)
+ internal
+ virtual
+ returns (uint256[] memory balances)
+ {
+ uint256 tokenCodeSize;
+ assembly {
+ tokenCodeSize := extcodesize(token)
+ }
+ require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
+
+ // ABI encode the aggregate call to Multicall3.
+ uint256 length = addresses.length;
+ IMulticall3.Call[] memory calls = new IMulticall3.Call[](length);
+ for (uint256 i = 0; i < length; ++i) {
+ // 0x70a08231 = bytes4("balanceOf(address)"))
+ calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
+ }
+
+ // Make the aggregate call.
+ (, bytes[] memory returnData) = multicall.aggregate(calls);
+
+ // ABI decode the return data and return the balances.
+ balances = new uint256[](length);
+ for (uint256 i = 0; i < length; ++i) {
+ balances[i] = abi.decode(returnData[i], (uint256));
+ }
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ PRIVATE FUNCTIONS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) {
+ return address(uint160(uint256(bytesValue)));
+ }
+
+ // This section is used to prevent the compilation of console, which shortens the compilation time when console is
+ // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid
+ // any breaking changes to function signatures.
+ function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn)
+ internal
+ pure
+ returns (function(bytes memory) internal pure fnOut)
+ {
+ assembly {
+ fnOut := fnIn
+ }
+ }
+
+ function _sendLogPayload(bytes memory payload) internal pure {
+ _castLogPayloadViewToPure(_sendLogPayloadView)(payload);
+ }
+
+ function _sendLogPayloadView(bytes memory payload) private view {
+ uint256 payloadLength = payload.length;
+ address consoleAddress = CONSOLE2_ADDRESS;
+ /// @solidity memory-safe-assembly
+ assembly {
+ let payloadStart := add(payload, 32)
+ let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
+ }
+ }
+
+ function console2_log_StdUtils(string memory p0) private pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
+ }
+
+ function console2_log_StdUtils(string memory p0, uint256 p1) private pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
+ }
+
+ function console2_log_StdUtils(string memory p0, string memory p1) private pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Test.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Test.sol
new file mode 100644
index 000000000..5ff60ea3f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Test.sol
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+// 💬 ABOUT
+// Forge Std's default Test.
+
+// 🧩 MODULES
+import {console} from "./console.sol";
+import {console2} from "./console2.sol";
+import {safeconsole} from "./safeconsole.sol";
+import {StdAssertions} from "./StdAssertions.sol";
+import {StdChains} from "./StdChains.sol";
+import {StdCheats} from "./StdCheats.sol";
+import {stdError} from "./StdError.sol";
+import {StdInvariant} from "./StdInvariant.sol";
+import {stdJson} from "./StdJson.sol";
+import {stdMath} from "./StdMath.sol";
+import {StdStorage, stdStorage} from "./StdStorage.sol";
+import {StdStyle} from "./StdStyle.sol";
+import {stdToml} from "./StdToml.sol";
+import {StdUtils} from "./StdUtils.sol";
+import {Vm} from "./Vm.sol";
+
+// 📦 BOILERPLATE
+import {TestBase} from "./Base.sol";
+
+// ⭐️ TEST
+abstract contract Test is TestBase, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils {
+ // Note: IS_TEST() must return true.
+ bool public IS_TEST = true;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Vm.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Vm.sol
new file mode 100644
index 000000000..591508c09
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/Vm.sol
@@ -0,0 +1,1968 @@
+// Automatically @generated by scripts/vm.py. Do not modify manually.
+
+// SPDX-License-Identifier: MIT OR Apache-2.0
+pragma solidity >=0.6.2 <0.9.0;
+pragma experimental ABIEncoderV2;
+
+/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may
+/// result in Script simulations differing from on-chain execution. It is recommended to only use
+/// these cheats in scripts.
+interface VmSafe {
+ /// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.
+ enum CallerMode {
+ // No caller modification is currently active.
+ None,
+ // A one time broadcast triggered by a `vm.broadcast()` call is currently active.
+ Broadcast,
+ // A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
+ RecurrentBroadcast,
+ // A one time prank triggered by a `vm.prank()` call is currently active.
+ Prank,
+ // A recurrent prank triggered by a `vm.startPrank()` call is currently active.
+ RecurrentPrank
+ }
+
+ /// The kind of account access that occurred.
+ enum AccountAccessKind {
+ // The account was called.
+ Call,
+ // The account was called via delegatecall.
+ DelegateCall,
+ // The account was called via callcode.
+ CallCode,
+ // The account was called via staticcall.
+ StaticCall,
+ // The account was created.
+ Create,
+ // The account was selfdestructed.
+ SelfDestruct,
+ // Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
+ Resume,
+ // The account's balance was read.
+ Balance,
+ // The account's codesize was read.
+ Extcodesize,
+ // The account's codehash was read.
+ Extcodehash,
+ // The account's code was copied.
+ Extcodecopy
+ }
+
+ /// Forge execution contexts.
+ enum ForgeContext {
+ // Test group execution context (test, coverage or snapshot).
+ TestGroup,
+ // `forge test` execution context.
+ Test,
+ // `forge coverage` execution context.
+ Coverage,
+ // `forge snapshot` execution context.
+ Snapshot,
+ // Script group execution context (dry run, broadcast or resume).
+ ScriptGroup,
+ // `forge script` execution context.
+ ScriptDryRun,
+ // `forge script --broadcast` execution context.
+ ScriptBroadcast,
+ // `forge script --resume` execution context.
+ ScriptResume,
+ // Unknown `forge` execution context.
+ Unknown
+ }
+
+ /// An Ethereum log. Returned by `getRecordedLogs`.
+ struct Log {
+ // The topics of the log, including the signature, if any.
+ bytes32[] topics;
+ // The raw data of the log.
+ bytes data;
+ // The address of the log's emitter.
+ address emitter;
+ }
+
+ /// An RPC URL and its alias. Returned by `rpcUrlStructs`.
+ struct Rpc {
+ // The alias of the RPC URL.
+ string key;
+ // The RPC URL.
+ string url;
+ }
+
+ /// An RPC log object. Returned by `eth_getLogs`.
+ struct EthGetLogs {
+ // The address of the log's emitter.
+ address emitter;
+ // The topics of the log, including the signature, if any.
+ bytes32[] topics;
+ // The raw data of the log.
+ bytes data;
+ // The block hash.
+ bytes32 blockHash;
+ // The block number.
+ uint64 blockNumber;
+ // The transaction hash.
+ bytes32 transactionHash;
+ // The transaction index in the block.
+ uint64 transactionIndex;
+ // The log index.
+ uint256 logIndex;
+ // Whether the log was removed.
+ bool removed;
+ }
+
+ /// A single entry in a directory listing. Returned by `readDir`.
+ struct DirEntry {
+ // The error message, if any.
+ string errorMessage;
+ // The path of the entry.
+ string path;
+ // The depth of the entry.
+ uint64 depth;
+ // Whether the entry is a directory.
+ bool isDir;
+ // Whether the entry is a symlink.
+ bool isSymlink;
+ }
+
+ /// Metadata information about a file.
+ /// This structure is returned from the `fsMetadata` function and represents known
+ /// metadata about a file such as its permissions, size, modification
+ /// times, etc.
+ struct FsMetadata {
+ // True if this metadata is for a directory.
+ bool isDir;
+ // True if this metadata is for a symlink.
+ bool isSymlink;
+ // The size of the file, in bytes, this metadata is for.
+ uint256 length;
+ // True if this metadata is for a readonly (unwritable) file.
+ bool readOnly;
+ // The last modification time listed in this metadata.
+ uint256 modified;
+ // The last access time of this metadata.
+ uint256 accessed;
+ // The creation time listed in this metadata.
+ uint256 created;
+ }
+
+ /// A wallet with a public and private key.
+ struct Wallet {
+ // The wallet's address.
+ address addr;
+ // The wallet's public key `X`.
+ uint256 publicKeyX;
+ // The wallet's public key `Y`.
+ uint256 publicKeyY;
+ // The wallet's private key.
+ uint256 privateKey;
+ }
+
+ /// The result of a `tryFfi` call.
+ struct FfiResult {
+ // The exit code of the call.
+ int32 exitCode;
+ // The optionally hex-decoded `stdout` data.
+ bytes stdout;
+ // The `stderr` data.
+ bytes stderr;
+ }
+
+ /// Information on the chain and fork.
+ struct ChainInfo {
+ // The fork identifier. Set to zero if no fork is active.
+ uint256 forkId;
+ // The chain ID of the current fork.
+ uint256 chainId;
+ }
+
+ /// The result of a `stopAndReturnStateDiff` call.
+ struct AccountAccess {
+ // The chain and fork the access occurred.
+ ChainInfo chainInfo;
+ // The kind of account access that determines what the account is.
+ // If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.
+ // If kind is Create, then the account is the newly created account.
+ // If kind is SelfDestruct, then the account is the selfdestruct recipient.
+ // If kind is a Resume, then account represents a account context that has resumed.
+ AccountAccessKind kind;
+ // The account that was accessed.
+ // It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.
+ address account;
+ // What accessed the account.
+ address accessor;
+ // If the account was initialized or empty prior to the access.
+ // An account is considered initialized if it has code, a
+ // non-zero nonce, or a non-zero balance.
+ bool initialized;
+ // The previous balance of the accessed account.
+ uint256 oldBalance;
+ // The potential new balance of the accessed account.
+ // That is, all balance changes are recorded here, even if reverts occurred.
+ uint256 newBalance;
+ // Code of the account deployed by CREATE.
+ bytes deployedCode;
+ // Value passed along with the account access
+ uint256 value;
+ // Input data provided to the CREATE or CALL
+ bytes data;
+ // If this access reverted in either the current or parent context.
+ bool reverted;
+ // An ordered list of storage accesses made during an account access operation.
+ StorageAccess[] storageAccesses;
+ // Call depth traversed during the recording of state differences
+ uint64 depth;
+ }
+
+ /// The storage accessed during an `AccountAccess`.
+ struct StorageAccess {
+ // The account whose storage was accessed.
+ address account;
+ // The slot that was accessed.
+ bytes32 slot;
+ // If the access was a write.
+ bool isWrite;
+ // The previous value of the slot.
+ bytes32 previousValue;
+ // The new value of the slot.
+ bytes32 newValue;
+ // If the access was reverted.
+ bool reverted;
+ }
+
+ /// Gas used. Returned by `lastCallGas`.
+ struct Gas {
+ // The gas limit of the call.
+ uint64 gasLimit;
+ // The total gas used.
+ uint64 gasTotalUsed;
+ // DEPRECATED: The amount of gas used for memory expansion. Ref:
+ uint64 gasMemoryUsed;
+ // The amount of gas refunded.
+ int64 gasRefunded;
+ // The amount of gas remaining.
+ uint64 gasRemaining;
+ }
+
+ // ======== Crypto ========
+
+ /// Derives a private key from the name, labels the account with that name, and returns the wallet.
+ function createWallet(string calldata walletLabel) external returns (Wallet memory wallet);
+
+ /// Generates a wallet from the private key and returns the wallet.
+ function createWallet(uint256 privateKey) external returns (Wallet memory wallet);
+
+ /// Generates a wallet from the private key, labels the account with that name, and returns the wallet.
+ function createWallet(uint256 privateKey, string calldata walletLabel) external returns (Wallet memory wallet);
+
+ /// Derive a private key from a provided mnenomic string (or mnenomic file path)
+ /// at the derivation path `m/44'/60'/0'/0/{index}`.
+ function deriveKey(string calldata mnemonic, uint32 index) external pure returns (uint256 privateKey);
+
+ /// Derive a private key from a provided mnenomic string (or mnenomic file path)
+ /// at `{derivationPath}{index}`.
+ function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index)
+ external
+ pure
+ returns (uint256 privateKey);
+
+ /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language
+ /// at the derivation path `m/44'/60'/0'/0/{index}`.
+ function deriveKey(string calldata mnemonic, uint32 index, string calldata language)
+ external
+ pure
+ returns (uint256 privateKey);
+
+ /// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language
+ /// at `{derivationPath}{index}`.
+ function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language)
+ external
+ pure
+ returns (uint256 privateKey);
+
+ /// Derives secp256r1 public key from the provided `privateKey`.
+ function publicKeyP256(uint256 privateKey) external pure returns (uint256 publicKeyX, uint256 publicKeyY);
+
+ /// Adds a private key to the local forge wallet and returns the address.
+ function rememberKey(uint256 privateKey) external returns (address keyAddr);
+
+ /// Signs data with a `Wallet`.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with `privateKey` using the secp256k1 curve.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ /// If `--sender` is provided, the signer with provided address is used, otherwise,
+ /// if exactly one signer is provided to the script, that signer is used.
+ /// Raises error if signer passed through `--sender` does not match any unlocked signers or
+ /// if `--sender` is not provided and not exactly one signer is passed to the script.
+ function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the
+ /// signature's `s` value, and the recovery id `v` in a single bytes32.
+ /// This format reduces the signature size from 65 to 64 bytes.
+ /// Raises error if none of the signers passed into the script have provided address.
+ function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);
+
+ /// Signs `digest` with `privateKey` using the secp256r1 curve.
+ function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s);
+
+ /// Signs data with a `Wallet`.
+ function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);
+
+ /// Signs `digest` with `privateKey` using the secp256k1 curve.
+ function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// If `--sender` is provided, the signer with provided address is used, otherwise,
+ /// if exactly one signer is provided to the script, that signer is used.
+ /// Raises error if signer passed through `--sender` does not match any unlocked signers or
+ /// if `--sender` is not provided and not exactly one signer is passed to the script.
+ function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
+
+ /// Signs `digest` with signer provided to script using the secp256k1 curve.
+ /// Raises error if none of the signers passed into the script have provided address.
+ function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);
+
+ // ======== Environment ========
+
+ /// Gets the environment variable `name` and parses it as `address`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envAddress(string calldata name) external view returns (address value);
+
+ /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bool`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBool(string calldata name) external view returns (bool value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBool(string calldata name, string calldata delim) external view returns (bool[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bytes32`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes32(string calldata name) external view returns (bytes32 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes32(string calldata name, string calldata delim) external view returns (bytes32[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bytes`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes(string calldata name) external view returns (bytes memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envBytes(string calldata name, string calldata delim) external view returns (bytes[] memory value);
+
+ /// Gets the environment variable `name` and returns true if it exists, else returns false.
+ function envExists(string calldata name) external view returns (bool result);
+
+ /// Gets the environment variable `name` and parses it as `int256`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envInt(string calldata name) external view returns (int256 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envInt(string calldata name, string calldata delim) external view returns (int256[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `bool`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, bool defaultValue) external view returns (bool value);
+
+ /// Gets the environment variable `name` and parses it as `uint256`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, uint256 defaultValue) external view returns (uint256 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, address[] calldata defaultValue)
+ external
+ view
+ returns (address[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, bytes32[] calldata defaultValue)
+ external
+ view
+ returns (bytes32[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, string[] calldata defaultValue)
+ external
+ view
+ returns (string[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, bytes[] calldata defaultValue)
+ external
+ view
+ returns (bytes[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `int256`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, int256 defaultValue) external view returns (int256 value);
+
+ /// Gets the environment variable `name` and parses it as `address`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, address defaultValue) external view returns (address value);
+
+ /// Gets the environment variable `name` and parses it as `bytes32`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, bytes32 defaultValue) external view returns (bytes32 value);
+
+ /// Gets the environment variable `name` and parses it as `string`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata defaultValue) external view returns (string memory value);
+
+ /// Gets the environment variable `name` and parses it as `bytes`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, bytes calldata defaultValue) external view returns (bytes memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, bool[] calldata defaultValue)
+ external
+ view
+ returns (bool[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, uint256[] calldata defaultValue)
+ external
+ view
+ returns (uint256[] memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`.
+ /// Reverts if the variable could not be parsed.
+ /// Returns `defaultValue` if the variable was not found.
+ function envOr(string calldata name, string calldata delim, int256[] calldata defaultValue)
+ external
+ view
+ returns (int256[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `string`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envString(string calldata name) external view returns (string memory value);
+
+ /// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envString(string calldata name, string calldata delim) external view returns (string[] memory value);
+
+ /// Gets the environment variable `name` and parses it as `uint256`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envUint(string calldata name) external view returns (uint256 value);
+
+ /// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`.
+ /// Reverts if the variable was not found or could not be parsed.
+ function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value);
+
+ /// Returns true if `forge` command was executed in given context.
+ function isContext(ForgeContext context) external view returns (bool result);
+
+ /// Sets environment variables.
+ function setEnv(string calldata name, string calldata value) external;
+
+ // ======== EVM ========
+
+ /// Gets all accessed reads and write slot from a `vm.record` session, for a given address.
+ function accesses(address target) external returns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
+
+ /// Gets the address for a given private key.
+ function addr(uint256 privateKey) external pure returns (address keyAddr);
+
+ /// Gets all the logs according to specified filter.
+ function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
+ external
+ returns (EthGetLogs[] memory logs);
+
+ /// Gets the current `block.blobbasefee`.
+ /// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,
+ /// and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getBlobBaseFee() external view returns (uint256 blobBaseFee);
+
+ /// Gets the current `block.number`.
+ /// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,
+ /// and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getBlockNumber() external view returns (uint256 height);
+
+ /// Gets the current `block.timestamp`.
+ /// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,
+ /// and as a result will get optimized out by the compiler.
+ /// See https://github.com/foundry-rs/foundry/issues/6180
+ function getBlockTimestamp() external view returns (uint256 timestamp);
+
+ /// Gets the map key and parent of a mapping at a given slot, for a given address.
+ function getMappingKeyAndParentOf(address target, bytes32 elementSlot)
+ external
+ returns (bool found, bytes32 key, bytes32 parent);
+
+ /// Gets the number of elements in the mapping at the given slot, for a given address.
+ function getMappingLength(address target, bytes32 mappingSlot) external returns (uint256 length);
+
+ /// Gets the elements at index idx of the mapping at the given slot, for a given address. The
+ /// index must be less than the length of the mapping (i.e. the number of keys in the mapping).
+ function getMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) external returns (bytes32 value);
+
+ /// Gets the nonce of an account.
+ function getNonce(address account) external view returns (uint64 nonce);
+
+ /// Get the nonce of a `Wallet`.
+ function getNonce(Wallet calldata wallet) external returns (uint64 nonce);
+
+ /// Gets all the recorded logs.
+ function getRecordedLogs() external returns (Log[] memory logs);
+
+ /// Gets the gas used in the last call.
+ function lastCallGas() external view returns (Gas memory gas);
+
+ /// Loads a storage slot from an address.
+ function load(address target, bytes32 slot) external view returns (bytes32 data);
+
+ /// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.
+ function pauseGasMetering() external;
+
+ /// Records all storage reads and writes.
+ function record() external;
+
+ /// Record all the transaction logs.
+ function recordLogs() external;
+
+ /// Reset gas metering (i.e. gas usage is set to gas limit).
+ function resetGasMetering() external;
+
+ /// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.
+ function resumeGasMetering() external;
+
+ /// Performs an Ethereum JSON-RPC request to the current fork URL.
+ function rpc(string calldata method, string calldata params) external returns (bytes memory data);
+
+ /// Performs an Ethereum JSON-RPC request to the given endpoint.
+ function rpc(string calldata urlOrAlias, string calldata method, string calldata params)
+ external
+ returns (bytes memory data);
+
+ /// Starts recording all map SSTOREs for later retrieval.
+ function startMappingRecording() external;
+
+ /// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
+ /// along with the context of the calls
+ function startStateDiffRecording() external;
+
+ /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.
+ function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses);
+
+ /// Stops recording all map SSTOREs for later retrieval and clears the recorded data.
+ function stopMappingRecording() external;
+
+ // ======== Filesystem ========
+
+ /// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
+ /// `path` is relative to the project root.
+ function closeFile(string calldata path) external;
+
+ /// Copies the contents of one file to another. This function will **overwrite** the contents of `to`.
+ /// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`.
+ /// Both `from` and `to` are relative to the project root.
+ function copyFile(string calldata from, string calldata to) external returns (uint64 copied);
+
+ /// Creates a new, empty directory at the provided path.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - User lacks permissions to modify `path`.
+ /// - A parent of the given path doesn't exist and `recursive` is false.
+ /// - `path` already exists and `recursive` is false.
+ /// `path` is relative to the project root.
+ function createDir(string calldata path, bool recursive) external;
+
+ /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function deployCode(string calldata artifactPath) external returns (address deployedAddress);
+
+ /// Deploys a contract from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ /// Additionally accepts abi-encoded constructor arguments.
+ function deployCode(string calldata artifactPath, bytes calldata constructorArgs)
+ external
+ returns (address deployedAddress);
+
+ /// Returns true if the given path points to an existing entity, else returns false.
+ function exists(string calldata path) external returns (bool result);
+
+ /// Performs a foreign function call via the terminal.
+ function ffi(string[] calldata commandInput) external returns (bytes memory result);
+
+ /// Given a path, query the file system to get information about a file, directory, etc.
+ function fsMetadata(string calldata path) external view returns (FsMetadata memory metadata);
+
+ /// Gets the artifact path from code (aka. creation code).
+ function getArtifactPathByCode(bytes calldata code) external view returns (string memory path);
+
+ /// Gets the artifact path from deployed code (aka. runtime code).
+ function getArtifactPathByDeployedCode(bytes calldata deployedCode) external view returns (string memory path);
+
+ /// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode);
+
+ /// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the
+ /// artifact in the form of :: where and parts are optional.
+ function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode);
+
+ /// Returns true if the path exists on disk and is pointing at a directory, else returns false.
+ function isDir(string calldata path) external returns (bool result);
+
+ /// Returns true if the path exists on disk and is pointing at a regular file, else returns false.
+ function isFile(string calldata path) external returns (bool result);
+
+ /// Get the path of the current project root.
+ function projectRoot() external view returns (string memory path);
+
+ /// Prompts the user for a string value in the terminal.
+ function prompt(string calldata promptText) external returns (string memory input);
+
+ /// Prompts the user for an address in the terminal.
+ function promptAddress(string calldata promptText) external returns (address);
+
+ /// Prompts the user for a hidden string value in the terminal.
+ function promptSecret(string calldata promptText) external returns (string memory input);
+
+ /// Prompts the user for hidden uint256 in the terminal (usually pk).
+ function promptSecretUint(string calldata promptText) external returns (uint256);
+
+ /// Prompts the user for uint256 in the terminal.
+ function promptUint(string calldata promptText) external returns (uint256);
+
+ /// Reads the directory at the given path recursively, up to `maxDepth`.
+ /// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned.
+ /// Follows symbolic links if `followLinks` is true.
+ function readDir(string calldata path) external view returns (DirEntry[] memory entries);
+
+ /// See `readDir(string)`.
+ function readDir(string calldata path, uint64 maxDepth) external view returns (DirEntry[] memory entries);
+
+ /// See `readDir(string)`.
+ function readDir(string calldata path, uint64 maxDepth, bool followLinks)
+ external
+ view
+ returns (DirEntry[] memory entries);
+
+ /// Reads the entire content of file to string. `path` is relative to the project root.
+ function readFile(string calldata path) external view returns (string memory data);
+
+ /// Reads the entire content of file as binary. `path` is relative to the project root.
+ function readFileBinary(string calldata path) external view returns (bytes memory data);
+
+ /// Reads next line of file to string.
+ function readLine(string calldata path) external view returns (string memory line);
+
+ /// Reads a symbolic link, returning the path that the link points to.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - `path` is not a symbolic link.
+ /// - `path` does not exist.
+ function readLink(string calldata linkPath) external view returns (string memory targetPath);
+
+ /// Removes a directory at the provided path.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - `path` doesn't exist.
+ /// - `path` isn't a directory.
+ /// - User lacks permissions to modify `path`.
+ /// - The directory is not empty and `recursive` is false.
+ /// `path` is relative to the project root.
+ function removeDir(string calldata path, bool recursive) external;
+
+ /// Removes a file from the filesystem.
+ /// This cheatcode will revert in the following situations, but is not limited to just these cases:
+ /// - `path` points to a directory.
+ /// - The file doesn't exist.
+ /// - The user lacks permissions to remove the file.
+ /// `path` is relative to the project root.
+ function removeFile(string calldata path) external;
+
+ /// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr.
+ function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result);
+
+ /// Returns the time since unix epoch in milliseconds.
+ function unixTime() external returns (uint256 milliseconds);
+
+ /// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
+ /// `path` is relative to the project root.
+ function writeFile(string calldata path, string calldata data) external;
+
+ /// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does.
+ /// `path` is relative to the project root.
+ function writeFileBinary(string calldata path, bytes calldata data) external;
+
+ /// Writes line to file, creating a file if it does not exist.
+ /// `path` is relative to the project root.
+ function writeLine(string calldata path, string calldata data) external;
+
+ // ======== JSON ========
+
+ /// Checks if `key` exists in a JSON object.
+ function keyExistsJson(string calldata json, string calldata key) external view returns (bool);
+
+ /// Parses a string of JSON data at `key` and coerces it to `address`.
+ function parseJsonAddress(string calldata json, string calldata key) external pure returns (address);
+
+ /// Parses a string of JSON data at `key` and coerces it to `address[]`.
+ function parseJsonAddressArray(string calldata json, string calldata key)
+ external
+ pure
+ returns (address[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bool`.
+ function parseJsonBool(string calldata json, string calldata key) external pure returns (bool);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bool[]`.
+ function parseJsonBoolArray(string calldata json, string calldata key) external pure returns (bool[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes`.
+ function parseJsonBytes(string calldata json, string calldata key) external pure returns (bytes memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes32`.
+ function parseJsonBytes32(string calldata json, string calldata key) external pure returns (bytes32);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.
+ function parseJsonBytes32Array(string calldata json, string calldata key)
+ external
+ pure
+ returns (bytes32[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `bytes[]`.
+ function parseJsonBytesArray(string calldata json, string calldata key) external pure returns (bytes[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `int256`.
+ function parseJsonInt(string calldata json, string calldata key) external pure returns (int256);
+
+ /// Parses a string of JSON data at `key` and coerces it to `int256[]`.
+ function parseJsonIntArray(string calldata json, string calldata key) external pure returns (int256[] memory);
+
+ /// Returns an array of all the keys in a JSON object.
+ function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys);
+
+ /// Parses a string of JSON data at `key` and coerces it to `string`.
+ function parseJsonString(string calldata json, string calldata key) external pure returns (string memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `string[]`.
+ function parseJsonStringArray(string calldata json, string calldata key) external pure returns (string[] memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to type array corresponding to `typeDescription`.
+ function parseJsonTypeArray(string calldata json, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of JSON data and coerces it to type corresponding to `typeDescription`.
+ function parseJsonType(string calldata json, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to type corresponding to `typeDescription`.
+ function parseJsonType(string calldata json, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of JSON data at `key` and coerces it to `uint256`.
+ function parseJsonUint(string calldata json, string calldata key) external pure returns (uint256);
+
+ /// Parses a string of JSON data at `key` and coerces it to `uint256[]`.
+ function parseJsonUintArray(string calldata json, string calldata key) external pure returns (uint256[] memory);
+
+ /// ABI-encodes a JSON object.
+ function parseJson(string calldata json) external pure returns (bytes memory abiEncodedData);
+
+ /// ABI-encodes a JSON object at `key`.
+ function parseJson(string calldata json, string calldata key) external pure returns (bytes memory abiEncodedData);
+
+ /// See `serializeJson`.
+ function serializeAddress(string calldata objectKey, string calldata valueKey, address value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeAddress(string calldata objectKey, string calldata valueKey, address[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBool(string calldata objectKey, string calldata valueKey, bool value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBool(string calldata objectKey, string calldata valueKey, bool[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes32(string calldata objectKey, string calldata valueKey, bytes32[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes(string calldata objectKey, string calldata valueKey, bytes calldata value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeBytes(string calldata objectKey, string calldata valueKey, bytes[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeInt(string calldata objectKey, string calldata valueKey, int256 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeInt(string calldata objectKey, string calldata valueKey, int256[] calldata values)
+ external
+ returns (string memory json);
+
+ /// Serializes a key and value to a JSON object stored in-memory that can be later written to a file.
+ /// Returns the stringified version of the specific JSON file up to that moment.
+ function serializeJson(string calldata objectKey, string calldata value) external returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeJsonType(string calldata typeDescription, bytes calldata value)
+ external
+ pure
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeJsonType(
+ string calldata objectKey,
+ string calldata valueKey,
+ string calldata typeDescription,
+ bytes calldata value
+ ) external returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeString(string calldata objectKey, string calldata valueKey, string calldata value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeString(string calldata objectKey, string calldata valueKey, string[] calldata values)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeUintToHex(string calldata objectKey, string calldata valueKey, uint256 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeUint(string calldata objectKey, string calldata valueKey, uint256 value)
+ external
+ returns (string memory json);
+
+ /// See `serializeJson`.
+ function serializeUint(string calldata objectKey, string calldata valueKey, uint256[] calldata values)
+ external
+ returns (string memory json);
+
+ /// Write a serialized JSON object to a file. If the file exists, it will be overwritten.
+ function writeJson(string calldata json, string calldata path) external;
+
+ /// Write a serialized JSON object to an **existing** JSON file, replacing a value with key =
+ /// This is useful to replace a specific value of a JSON file, without having to parse the entire thing.
+ function writeJson(string calldata json, string calldata path, string calldata valueKey) external;
+
+ /// Checks if `key` exists in a JSON object
+ /// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions.
+ function keyExists(string calldata json, string calldata key) external view returns (bool);
+
+ // ======== Scripting ========
+
+ /// Takes a signed transaction and broadcasts it to the network.
+ function broadcastRawTransaction(bytes calldata data) external;
+
+ /// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain.
+ /// Broadcasting address is determined by checking the following in order:
+ /// 1. If `--sender` argument was provided, that address is used.
+ /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
+ /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
+ function broadcast() external;
+
+ /// Has the next call (at this call depth only) create a transaction with the address provided
+ /// as the sender that can later be signed and sent onchain.
+ function broadcast(address signer) external;
+
+ /// Has the next call (at this call depth only) create a transaction with the private key
+ /// provided as the sender that can later be signed and sent onchain.
+ function broadcast(uint256 privateKey) external;
+
+ /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain.
+ /// Broadcasting address is determined by checking the following in order:
+ /// 1. If `--sender` argument was provided, that address is used.
+ /// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used.
+ /// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.
+ function startBroadcast() external;
+
+ /// Has all subsequent calls (at this call depth only) create transactions with the address
+ /// provided that can later be signed and sent onchain.
+ function startBroadcast(address signer) external;
+
+ /// Has all subsequent calls (at this call depth only) create transactions with the private key
+ /// provided that can later be signed and sent onchain.
+ function startBroadcast(uint256 privateKey) external;
+
+ /// Stops collecting onchain transactions.
+ function stopBroadcast() external;
+
+ // ======== String ========
+
+ /// Returns the index of the first occurrence of a `key` in an `input` string.
+ /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found.
+ /// Returns 0 in case of an empty `key`.
+ function indexOf(string calldata input, string calldata key) external pure returns (uint256);
+
+ /// Parses the given `string` into an `address`.
+ function parseAddress(string calldata stringifiedValue) external pure returns (address parsedValue);
+
+ /// Parses the given `string` into a `bool`.
+ function parseBool(string calldata stringifiedValue) external pure returns (bool parsedValue);
+
+ /// Parses the given `string` into `bytes`.
+ function parseBytes(string calldata stringifiedValue) external pure returns (bytes memory parsedValue);
+
+ /// Parses the given `string` into a `bytes32`.
+ function parseBytes32(string calldata stringifiedValue) external pure returns (bytes32 parsedValue);
+
+ /// Parses the given `string` into a `int256`.
+ function parseInt(string calldata stringifiedValue) external pure returns (int256 parsedValue);
+
+ /// Parses the given `string` into a `uint256`.
+ function parseUint(string calldata stringifiedValue) external pure returns (uint256 parsedValue);
+
+ /// Replaces occurrences of `from` in the given `string` with `to`.
+ function replace(string calldata input, string calldata from, string calldata to)
+ external
+ pure
+ returns (string memory output);
+
+ /// Splits the given `string` into an array of strings divided by the `delimiter`.
+ function split(string calldata input, string calldata delimiter) external pure returns (string[] memory outputs);
+
+ /// Converts the given `string` value to Lowercase.
+ function toLowercase(string calldata input) external pure returns (string memory output);
+
+ /// Converts the given value to a `string`.
+ function toString(address value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(bytes calldata value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(bytes32 value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(bool value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(uint256 value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given value to a `string`.
+ function toString(int256 value) external pure returns (string memory stringifiedValue);
+
+ /// Converts the given `string` value to Uppercase.
+ function toUppercase(string calldata input) external pure returns (string memory output);
+
+ /// Trims leading and trailing whitespace from the given `string` value.
+ function trim(string calldata input) external pure returns (string memory output);
+
+ // ======== Testing ========
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message.
+ function assertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqAbsDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message.
+ function assertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqAbsDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) external pure;
+
+ /// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Includes error message into revert string on failure.
+ function assertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) external pure;
+
+ /// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.
+ /// Includes error message into revert string on failure.
+ function assertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message.
+ function assertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals)
+ external
+ pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqRelDecimal(
+ uint256 left,
+ uint256 right,
+ uint256 maxPercentDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message.
+ function assertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals)
+ external
+ pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertApproxEqRelDecimal(
+ int256 left,
+ int256 right,
+ uint256 maxPercentDelta,
+ uint256 decimals,
+ string calldata error
+ ) external pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) external pure;
+
+ /// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Includes error message into revert string on failure.
+ function assertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, string calldata error)
+ external
+ pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) external pure;
+
+ /// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`.
+ /// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%
+ /// Includes error message into revert string on failure.
+ function assertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, string calldata error)
+ external
+ pure;
+
+ /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `int256` values are equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `bool` values are equal.
+ function assertEq(bool left, bool right) external pure;
+
+ /// Asserts that two `bool` values are equal and includes error message into revert string on failure.
+ function assertEq(bool left, bool right, string calldata error) external pure;
+
+ /// Asserts that two `string` values are equal.
+ function assertEq(string calldata left, string calldata right) external pure;
+
+ /// Asserts that two `string` values are equal and includes error message into revert string on failure.
+ function assertEq(string calldata left, string calldata right, string calldata error) external pure;
+
+ /// Asserts that two `bytes` values are equal.
+ function assertEq(bytes calldata left, bytes calldata right) external pure;
+
+ /// Asserts that two `bytes` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bool` values are equal.
+ function assertEq(bool[] calldata left, bool[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.
+ function assertEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `uint256 values are equal.
+ function assertEq(uint256[] calldata left, uint256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.
+ function assertEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `int256` values are equal.
+ function assertEq(int256[] calldata left, int256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.
+ function assertEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are equal.
+ function assertEq(uint256 left, uint256 right) external pure;
+
+ /// Asserts that two arrays of `address` values are equal.
+ function assertEq(address[] calldata left, address[] calldata right) external pure;
+
+ /// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.
+ function assertEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are equal.
+ function assertEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `string` values are equal.
+ function assertEq(string[] calldata left, string[] calldata right) external pure;
+
+ /// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.
+ function assertEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes` values are equal.
+ function assertEq(bytes[] calldata left, bytes[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are equal and includes error message into revert string on failure.
+ function assertEq(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are equal.
+ function assertEq(int256 left, int256 right) external pure;
+
+ /// Asserts that two `int256` values are equal and includes error message into revert string on failure.
+ function assertEq(int256 left, int256 right, string calldata error) external pure;
+
+ /// Asserts that two `address` values are equal.
+ function assertEq(address left, address right) external pure;
+
+ /// Asserts that two `address` values are equal and includes error message into revert string on failure.
+ function assertEq(address left, address right, string calldata error) external pure;
+
+ /// Asserts that two `bytes32` values are equal.
+ function assertEq(bytes32 left, bytes32 right) external pure;
+
+ /// Asserts that two `bytes32` values are equal and includes error message into revert string on failure.
+ function assertEq(bytes32 left, bytes32 right, string calldata error) external pure;
+
+ /// Asserts that the given condition is false.
+ function assertFalse(bool condition) external pure;
+
+ /// Asserts that the given condition is false and includes error message into revert string on failure.
+ function assertFalse(bool condition, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ function assertGe(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertGe(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ function assertGe(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertGe(int256 left, int256 right, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message.
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message.
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertGtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ function assertGt(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be greater than second.
+ /// Includes error message into revert string on failure.
+ function assertGt(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ function assertGt(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be greater than second.
+ /// Includes error message into revert string on failure.
+ function assertGt(int256 left, int256 right, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLeDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message.
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLeDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ function assertLe(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertLe(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ function assertLe(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than or equal to second.
+ /// Includes error message into revert string on failure.
+ function assertLe(int256 left, int256 right, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message.
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLtDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message.
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ /// Formats values with decimals in failure message. Includes error message into revert string on failure.
+ function assertLtDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ function assertLt(uint256 left, uint256 right) external pure;
+
+ /// Compares two `uint256` values. Expects first value to be less than second.
+ /// Includes error message into revert string on failure.
+ function assertLt(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ function assertLt(int256 left, int256 right) external pure;
+
+ /// Compares two `int256` values. Expects first value to be less than second.
+ /// Includes error message into revert string on failure.
+ function assertLt(int256 left, int256 right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals) external pure;
+
+ /// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.
+ /// Includes error message into revert string on failure.
+ function assertNotEqDecimal(int256 left, int256 right, uint256 decimals, string calldata error) external pure;
+
+ /// Asserts that two `bool` values are not equal.
+ function assertNotEq(bool left, bool right) external pure;
+
+ /// Asserts that two `bool` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bool left, bool right, string calldata error) external pure;
+
+ /// Asserts that two `string` values are not equal.
+ function assertNotEq(string calldata left, string calldata right) external pure;
+
+ /// Asserts that two `string` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(string calldata left, string calldata right, string calldata error) external pure;
+
+ /// Asserts that two `bytes` values are not equal.
+ function assertNotEq(bytes calldata left, bytes calldata right) external pure;
+
+ /// Asserts that two `bytes` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes calldata left, bytes calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bool` values are not equal.
+ function assertNotEq(bool[] calldata left, bool[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bool[] calldata left, bool[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `uint256` values are not equal.
+ function assertNotEq(uint256[] calldata left, uint256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(uint256[] calldata left, uint256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `int256` values are not equal.
+ function assertNotEq(int256[] calldata left, int256[] calldata right) external pure;
+
+ /// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(int256[] calldata left, int256[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are not equal.
+ function assertNotEq(uint256 left, uint256 right) external pure;
+
+ /// Asserts that two arrays of `address` values are not equal.
+ function assertNotEq(address[] calldata left, address[] calldata right) external pure;
+
+ /// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(address[] calldata left, address[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are not equal.
+ function assertNotEq(bytes32[] calldata left, bytes32[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes32[] calldata left, bytes32[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `string` values are not equal.
+ function assertNotEq(string[] calldata left, string[] calldata right) external pure;
+
+ /// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(string[] calldata left, string[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two arrays of `bytes` values are not equal.
+ function assertNotEq(bytes[] calldata left, bytes[] calldata right) external pure;
+
+ /// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes[] calldata left, bytes[] calldata right, string calldata error) external pure;
+
+ /// Asserts that two `uint256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(uint256 left, uint256 right, string calldata error) external pure;
+
+ /// Asserts that two `int256` values are not equal.
+ function assertNotEq(int256 left, int256 right) external pure;
+
+ /// Asserts that two `int256` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(int256 left, int256 right, string calldata error) external pure;
+
+ /// Asserts that two `address` values are not equal.
+ function assertNotEq(address left, address right) external pure;
+
+ /// Asserts that two `address` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(address left, address right, string calldata error) external pure;
+
+ /// Asserts that two `bytes32` values are not equal.
+ function assertNotEq(bytes32 left, bytes32 right) external pure;
+
+ /// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.
+ function assertNotEq(bytes32 left, bytes32 right, string calldata error) external pure;
+
+ /// Asserts that the given condition is true.
+ function assertTrue(bool condition) external pure;
+
+ /// Asserts that the given condition is true and includes error message into revert string on failure.
+ function assertTrue(bool condition, string calldata error) external pure;
+
+ /// If the condition is false, discard this run's fuzz inputs and generate new ones.
+ function assume(bool condition) external pure;
+
+ /// Discard this run's fuzz inputs and generate new ones if next call reverted.
+ function assumeNoRevert() external pure;
+
+ /// Writes a breakpoint to jump to in the debugger.
+ function breakpoint(string calldata char) external;
+
+ /// Writes a conditional breakpoint to jump to in the debugger.
+ function breakpoint(string calldata char, bool value) external;
+
+ /// Returns the Foundry version.
+ /// Format: ++
+ /// Sample output: 0.2.0+faa94c384+202407110019
+ /// Note: Build timestamps may vary slightly across platforms due to separate CI jobs.
+ /// For reliable version comparisons, use YYYYMMDD0000 format (e.g., >= 202407110000)
+ /// to compare timestamps while ignoring minor time differences.
+ function getFoundryVersion() external view returns (string memory version);
+
+ /// Returns the RPC url for the given alias.
+ function rpcUrl(string calldata rpcAlias) external view returns (string memory json);
+
+ /// Returns all rpc urls and their aliases as structs.
+ function rpcUrlStructs() external view returns (Rpc[] memory urls);
+
+ /// Returns all rpc urls and their aliases `[alias, url][]`.
+ function rpcUrls() external view returns (string[2][] memory urls);
+
+ /// Suspends execution of the main thread for `duration` milliseconds.
+ function sleep(uint256 duration) external;
+
+ // ======== Toml ========
+
+ /// Checks if `key` exists in a TOML table.
+ function keyExistsToml(string calldata toml, string calldata key) external view returns (bool);
+
+ /// Parses a string of TOML data at `key` and coerces it to `address`.
+ function parseTomlAddress(string calldata toml, string calldata key) external pure returns (address);
+
+ /// Parses a string of TOML data at `key` and coerces it to `address[]`.
+ function parseTomlAddressArray(string calldata toml, string calldata key)
+ external
+ pure
+ returns (address[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bool`.
+ function parseTomlBool(string calldata toml, string calldata key) external pure returns (bool);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bool[]`.
+ function parseTomlBoolArray(string calldata toml, string calldata key) external pure returns (bool[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes`.
+ function parseTomlBytes(string calldata toml, string calldata key) external pure returns (bytes memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes32`.
+ function parseTomlBytes32(string calldata toml, string calldata key) external pure returns (bytes32);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes32[]`.
+ function parseTomlBytes32Array(string calldata toml, string calldata key)
+ external
+ pure
+ returns (bytes32[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `bytes[]`.
+ function parseTomlBytesArray(string calldata toml, string calldata key) external pure returns (bytes[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `int256`.
+ function parseTomlInt(string calldata toml, string calldata key) external pure returns (int256);
+
+ /// Parses a string of TOML data at `key` and coerces it to `int256[]`.
+ function parseTomlIntArray(string calldata toml, string calldata key) external pure returns (int256[] memory);
+
+ /// Returns an array of all the keys in a TOML table.
+ function parseTomlKeys(string calldata toml, string calldata key) external pure returns (string[] memory keys);
+
+ /// Parses a string of TOML data at `key` and coerces it to `string`.
+ function parseTomlString(string calldata toml, string calldata key) external pure returns (string memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `string[]`.
+ function parseTomlStringArray(string calldata toml, string calldata key) external pure returns (string[] memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to type array corresponding to `typeDescription`.
+ function parseTomlTypeArray(string calldata toml, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of TOML data and coerces it to type corresponding to `typeDescription`.
+ function parseTomlType(string calldata toml, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to type corresponding to `typeDescription`.
+ function parseTomlType(string calldata toml, string calldata key, string calldata typeDescription)
+ external
+ pure
+ returns (bytes memory);
+
+ /// Parses a string of TOML data at `key` and coerces it to `uint256`.
+ function parseTomlUint(string calldata toml, string calldata key) external pure returns (uint256);
+
+ /// Parses a string of TOML data at `key` and coerces it to `uint256[]`.
+ function parseTomlUintArray(string calldata toml, string calldata key) external pure returns (uint256[] memory);
+
+ /// ABI-encodes a TOML table.
+ function parseToml(string calldata toml) external pure returns (bytes memory abiEncodedData);
+
+ /// ABI-encodes a TOML table at `key`.
+ function parseToml(string calldata toml, string calldata key) external pure returns (bytes memory abiEncodedData);
+
+ /// Takes serialized JSON, converts to TOML and write a serialized TOML to a file.
+ function writeToml(string calldata json, string calldata path) external;
+
+ /// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key =
+ /// This is useful to replace a specific value of a TOML file, without having to parse the entire thing.
+ function writeToml(string calldata json, string calldata path, string calldata valueKey) external;
+
+ // ======== Utilities ========
+
+ /// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.
+ function computeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
+ external
+ pure
+ returns (address);
+
+ /// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer.
+ function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) external pure returns (address);
+
+ /// Compute the address a contract will be deployed at for a given deployer address and nonce.
+ function computeCreateAddress(address deployer, uint256 nonce) external pure returns (address);
+
+ /// Utility cheatcode to copy storage of `from` contract to another `to` contract.
+ function copyStorage(address from, address to) external;
+
+ /// Returns ENS namehash for provided string.
+ function ensNamehash(string calldata name) external pure returns (bytes32);
+
+ /// Gets the label for the specified address.
+ function getLabel(address account) external view returns (string memory currentLabel);
+
+ /// Labels an address in call traces.
+ function label(address account, string calldata newLabel) external;
+
+ /// Pauses collection of call traces. Useful in cases when you want to skip tracing of
+ /// complex calls which are not useful for debugging.
+ function pauseTracing() external view;
+
+ /// Returns a random `address`.
+ function randomAddress() external returns (address);
+
+ /// Returns an random `bool`.
+ function randomBool() external view returns (bool);
+
+ /// Returns an random byte array value of the given length.
+ function randomBytes(uint256 len) external view returns (bytes memory);
+
+ /// Returns an random `int256` value.
+ function randomInt() external view returns (int256);
+
+ /// Returns an random `int256` value of given bits.
+ function randomInt(uint256 bits) external view returns (int256);
+
+ /// Returns a random uint256 value.
+ function randomUint() external returns (uint256);
+
+ /// Returns random uint256 value between the provided range (=min..=max).
+ function randomUint(uint256 min, uint256 max) external returns (uint256);
+
+ /// Returns an random `uint256` value of given bits.
+ function randomUint(uint256 bits) external view returns (uint256);
+
+ /// Unpauses collection of call traces.
+ function resumeTracing() external view;
+
+ /// Utility cheatcode to set arbitrary storage for given target address.
+ function setArbitraryStorage(address target) external;
+
+ /// Encodes a `bytes` value to a base64url string.
+ function toBase64URL(bytes calldata data) external pure returns (string memory);
+
+ /// Encodes a `string` value to a base64url string.
+ function toBase64URL(string calldata data) external pure returns (string memory);
+
+ /// Encodes a `bytes` value to a base64 string.
+ function toBase64(bytes calldata data) external pure returns (string memory);
+
+ /// Encodes a `string` value to a base64 string.
+ function toBase64(string calldata data) external pure returns (string memory);
+}
+
+/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used
+/// in tests, but it is not recommended to use these cheats in scripts.
+interface Vm is VmSafe {
+ // ======== EVM ========
+
+ /// Returns the identifier of the currently active fork. Reverts if no fork is currently active.
+ function activeFork() external view returns (uint256 forkId);
+
+ /// In forking mode, explicitly grant the given address cheatcode access.
+ function allowCheatcodes(address account) external;
+
+ /// Sets `block.blobbasefee`
+ function blobBaseFee(uint256 newBlobBaseFee) external;
+
+ /// Sets the blobhashes in the transaction.
+ /// Not available on EVM versions before Cancun.
+ /// If used on unsupported EVM versions it will revert.
+ function blobhashes(bytes32[] calldata hashes) external;
+
+ /// Sets `block.chainid`.
+ function chainId(uint256 newChainId) external;
+
+ /// Clears all mocked calls.
+ function clearMockedCalls() external;
+
+ /// Sets `block.coinbase`.
+ function coinbase(address newCoinbase) external;
+
+ /// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork.
+ function createFork(string calldata urlOrAlias) external returns (uint256 forkId);
+
+ /// Creates a new fork with the given endpoint and block and returns the identifier of the fork.
+ function createFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
+
+ /// Creates a new fork with the given endpoint and at the block the given transaction was mined in,
+ /// replays all transaction mined in the block before the transaction, and returns the identifier of the fork.
+ function createFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
+
+ /// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork.
+ function createSelectFork(string calldata urlOrAlias) external returns (uint256 forkId);
+
+ /// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork.
+ function createSelectFork(string calldata urlOrAlias, uint256 blockNumber) external returns (uint256 forkId);
+
+ /// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in,
+ /// replays all transaction mined in the block before the transaction, returns the identifier of the fork.
+ function createSelectFork(string calldata urlOrAlias, bytes32 txHash) external returns (uint256 forkId);
+
+ /// Sets an address' balance.
+ function deal(address account, uint256 newBalance) external;
+
+ /// Removes the snapshot with the given ID created by `snapshot`.
+ /// Takes the snapshot ID to delete.
+ /// Returns `true` if the snapshot was successfully deleted.
+ /// Returns `false` if the snapshot does not exist.
+ function deleteSnapshot(uint256 snapshotId) external returns (bool success);
+
+ /// Removes _all_ snapshots previously created by `snapshot`.
+ function deleteSnapshots() external;
+
+ /// Sets `block.difficulty`.
+ /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead.
+ /// Reverts if used on unsupported EVM versions.
+ function difficulty(uint256 newDifficulty) external;
+
+ /// Dump a genesis JSON file's `allocs` to disk.
+ function dumpState(string calldata pathToStateJson) external;
+
+ /// Sets an address' code.
+ function etch(address target, bytes calldata newRuntimeBytecode) external;
+
+ /// Sets `block.basefee`.
+ function fee(uint256 newBasefee) external;
+
+ /// Gets the blockhashes from the current transaction.
+ /// Not available on EVM versions before Cancun.
+ /// If used on unsupported EVM versions it will revert.
+ function getBlobhashes() external view returns (bytes32[] memory hashes);
+
+ /// Returns true if the account is marked as persistent.
+ function isPersistent(address account) external view returns (bool persistent);
+
+ /// Load a genesis JSON file's `allocs` into the in-memory revm state.
+ function loadAllocs(string calldata pathToAllocsJson) external;
+
+ /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup
+ /// Meaning, changes made to the state of this account will be kept when switching forks.
+ function makePersistent(address account) external;
+
+ /// See `makePersistent(address)`.
+ function makePersistent(address account0, address account1) external;
+
+ /// See `makePersistent(address)`.
+ function makePersistent(address account0, address account1, address account2) external;
+
+ /// See `makePersistent(address)`.
+ function makePersistent(address[] calldata accounts) external;
+
+ /// Reverts a call to an address with specified revert data.
+ function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external;
+
+ /// Reverts a call to an address with a specific `msg.value`, with specified revert data.
+ function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData)
+ external;
+
+ /// Mocks a call to an address, returning specified data.
+ /// Calldata can either be strict or a partial match, e.g. if you only
+ /// pass a Solidity selector to the expected calldata, then the entire Solidity
+ /// function will be mocked.
+ function mockCall(address callee, bytes calldata data, bytes calldata returnData) external;
+
+ /// Mocks a call to an address with a specific `msg.value`, returning specified data.
+ /// Calldata match takes precedence over `msg.value` in case of ambiguity.
+ function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external;
+
+ /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls
+ /// `target` with the same calldata. This functionality is similar to a delegate call made to
+ /// `target` contract from `callee`.
+ /// Can be used to substitute a call to a function with another implementation that captures
+ /// the primary logic of the original function but is easier to reason about.
+ /// If calldata is not a strict match then partial match by selector is attempted.
+ function mockFunction(address callee, address target, bytes calldata data) external;
+
+ /// Sets the *next* call's `msg.sender` to be the input address.
+ function prank(address msgSender) external;
+
+ /// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.
+ function prank(address msgSender, address txOrigin) external;
+
+ /// Sets `block.prevrandao`.
+ /// Not available on EVM versions before Paris. Use `difficulty` instead.
+ /// If used on unsupported EVM versions it will revert.
+ function prevrandao(bytes32 newPrevrandao) external;
+
+ /// Sets `block.prevrandao`.
+ /// Not available on EVM versions before Paris. Use `difficulty` instead.
+ /// If used on unsupported EVM versions it will revert.
+ function prevrandao(uint256 newPrevrandao) external;
+
+ /// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification.
+ function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin);
+
+ /// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts.
+ function resetNonce(address account) external;
+
+ /// Revert the state of the EVM to a previous snapshot
+ /// Takes the snapshot ID to revert to.
+ /// Returns `true` if the snapshot was successfully reverted.
+ /// Returns `false` if the snapshot does not exist.
+ /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`.
+ function revertTo(uint256 snapshotId) external returns (bool success);
+
+ /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots
+ /// Takes the snapshot ID to revert to.
+ /// Returns `true` if the snapshot was successfully reverted and deleted.
+ /// Returns `false` if the snapshot does not exist.
+ function revertToAndDelete(uint256 snapshotId) external returns (bool success);
+
+ /// Revokes persistent status from the address, previously added via `makePersistent`.
+ function revokePersistent(address account) external;
+
+ /// See `revokePersistent(address)`.
+ function revokePersistent(address[] calldata accounts) external;
+
+ /// Sets `block.height`.
+ function roll(uint256 newHeight) external;
+
+ /// Updates the currently active fork to given block number
+ /// This is similar to `roll` but for the currently active fork.
+ function rollFork(uint256 blockNumber) external;
+
+ /// Updates the currently active fork to given transaction. This will `rollFork` with the number
+ /// of the block the transaction was mined in and replays all transaction mined before it in the block.
+ function rollFork(bytes32 txHash) external;
+
+ /// Updates the given fork to given block number.
+ function rollFork(uint256 forkId, uint256 blockNumber) external;
+
+ /// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block.
+ function rollFork(uint256 forkId, bytes32 txHash) external;
+
+ /// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
+ function selectFork(uint256 forkId) external;
+
+ /// Set blockhash for the current block.
+ /// It only sets the blockhash for blocks where `block.number - 256 <= number < block.number`.
+ function setBlockhash(uint256 blockNumber, bytes32 blockHash) external;
+
+ /// Sets the nonce of an account. Must be higher than the current nonce of the account.
+ function setNonce(address account, uint64 newNonce) external;
+
+ /// Sets the nonce of an account to an arbitrary value.
+ function setNonceUnsafe(address account, uint64 newNonce) external;
+
+ /// Snapshot the current state of the evm.
+ /// Returns the ID of the snapshot that was created.
+ /// To revert a snapshot use `revertTo`.
+ function snapshot() external returns (uint256 snapshotId);
+
+ /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called.
+ function startPrank(address msgSender) external;
+
+ /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.
+ function startPrank(address msgSender, address txOrigin) external;
+
+ /// Resets subsequent calls' `msg.sender` to be `address(this)`.
+ function stopPrank() external;
+
+ /// Stores a value to an address' storage slot.
+ function store(address target, bytes32 slot, bytes32 value) external;
+
+ /// Fetches the given transaction from the active fork and executes it on the current state.
+ function transact(bytes32 txHash) external;
+
+ /// Fetches the given transaction from the given fork and executes it on the current state.
+ function transact(uint256 forkId, bytes32 txHash) external;
+
+ /// Sets `tx.gasprice`.
+ function txGasPrice(uint256 newGasPrice) external;
+
+ /// Sets `block.timestamp`.
+ function warp(uint256 newTimestamp) external;
+
+ // ======== Testing ========
+
+ /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
+ function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external;
+
+ /// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.
+ function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count)
+ external;
+
+ /// Expects a call to an address with the specified calldata.
+ /// Calldata can either be a strict or a partial match.
+ function expectCall(address callee, bytes calldata data) external;
+
+ /// Expects given number of calls to an address with the specified calldata.
+ function expectCall(address callee, bytes calldata data, uint64 count) external;
+
+ /// Expects a call to an address with the specified `msg.value` and calldata.
+ function expectCall(address callee, uint256 msgValue, bytes calldata data) external;
+
+ /// Expects given number of calls to an address with the specified `msg.value` and calldata.
+ function expectCall(address callee, uint256 msgValue, bytes calldata data, uint64 count) external;
+
+ /// Expect a call to an address with the specified `msg.value`, gas, and calldata.
+ function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data) external;
+
+ /// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata.
+ function expectCall(address callee, uint256 msgValue, uint64 gas, bytes calldata data, uint64 count) external;
+
+ /// Prepare an expected anonymous log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
+ /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
+ function expectEmitAnonymous(bool checkTopic0, bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData)
+ external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmitAnonymous(
+ bool checkTopic0,
+ bool checkTopic1,
+ bool checkTopic2,
+ bool checkTopic3,
+ bool checkData,
+ address emitter
+ ) external;
+
+ /// Prepare an expected anonymous log with all topic and data checks enabled.
+ /// Call this function, then emit an anonymous event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data.
+ function expectEmitAnonymous() external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmitAnonymous(address emitter) external;
+
+ /// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.).
+ /// Call this function, then emit an event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
+ function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
+ external;
+
+ /// Prepare an expected log with all topic and data checks enabled.
+ /// Call this function, then emit an event, then call a function. Internally after the call, we check if
+ /// logs were emitted in the expected order with the expected topics and data.
+ function expectEmit() external;
+
+ /// Same as the previous method, but also checks supplied address against emitting contract.
+ function expectEmit(address emitter) external;
+
+ /// Expects an error on next call that starts with the revert data.
+ function expectPartialRevert(bytes4 revertData) external;
+
+ /// Expects an error on next call to reverter address, that starts with the revert data.
+ function expectPartialRevert(bytes4 revertData, address reverter) external;
+
+ /// Expects an error on next call with any revert data.
+ function expectRevert() external;
+
+ /// Expects an error on next call that exactly matches the revert data.
+ function expectRevert(bytes4 revertData) external;
+
+ /// Expects an error on next call that exactly matches the revert data.
+ function expectRevert(bytes calldata revertData) external;
+
+ /// Expects an error with any revert data on next call to reverter address.
+ function expectRevert(address reverter) external;
+
+ /// Expects an error from reverter address on next call, with any revert data.
+ function expectRevert(bytes4 revertData, address reverter) external;
+
+ /// Expects an error from reverter address on next call, that exactly matches the revert data.
+ function expectRevert(bytes calldata revertData, address reverter) external;
+
+ /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other
+ /// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.
+ function expectSafeMemory(uint64 min, uint64 max) external;
+
+ /// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext.
+ /// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges
+ /// to the set.
+ function expectSafeMemoryCall(uint64 min, uint64 max) external;
+
+ /// Marks a test as skipped. Must be called at the top level of a test.
+ function skip(bool skipTest) external;
+
+ /// Marks a test as skipped with a reason. Must be called at the top level of a test.
+ function skip(bool skipTest, string calldata reason) external;
+
+ /// Stops all safe memory expectation in the current subcontext.
+ function stopExpectSafeMemory() external;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/console.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/console.sol
new file mode 100644
index 000000000..4fdb6679e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/console.sol
@@ -0,0 +1,1560 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.4.22 <0.9.0;
+
+library console {
+ address constant CONSOLE_ADDRESS =
+ 0x000000000000000000636F6e736F6c652e6c6f67;
+
+ function _sendLogPayloadImplementation(bytes memory payload) internal view {
+ address consoleAddress = CONSOLE_ADDRESS;
+ /// @solidity memory-safe-assembly
+ assembly {
+ pop(
+ staticcall(
+ gas(),
+ consoleAddress,
+ add(payload, 32),
+ mload(payload),
+ 0,
+ 0
+ )
+ )
+ }
+ }
+
+ function _castToPure(
+ function(bytes memory) internal view fnIn
+ ) internal pure returns (function(bytes memory) pure fnOut) {
+ assembly {
+ fnOut := fnIn
+ }
+ }
+
+ function _sendLogPayload(bytes memory payload) internal pure {
+ _castToPure(_sendLogPayloadImplementation)(payload);
+ }
+
+ function log() internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log()"));
+ }
+
+ function logInt(int256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
+ }
+
+ function logUint(uint256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
+ }
+
+ function logString(string memory p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
+ }
+
+ function logBool(bool p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
+ }
+
+ function logAddress(address p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
+ }
+
+ function logBytes(bytes memory p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
+ }
+
+ function logBytes1(bytes1 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
+ }
+
+ function logBytes2(bytes2 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
+ }
+
+ function logBytes3(bytes3 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
+ }
+
+ function logBytes4(bytes4 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
+ }
+
+ function logBytes5(bytes5 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
+ }
+
+ function logBytes6(bytes6 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
+ }
+
+ function logBytes7(bytes7 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
+ }
+
+ function logBytes8(bytes8 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
+ }
+
+ function logBytes9(bytes9 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
+ }
+
+ function logBytes10(bytes10 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
+ }
+
+ function logBytes11(bytes11 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
+ }
+
+ function logBytes12(bytes12 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
+ }
+
+ function logBytes13(bytes13 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
+ }
+
+ function logBytes14(bytes14 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
+ }
+
+ function logBytes15(bytes15 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
+ }
+
+ function logBytes16(bytes16 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
+ }
+
+ function logBytes17(bytes17 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
+ }
+
+ function logBytes18(bytes18 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
+ }
+
+ function logBytes19(bytes19 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
+ }
+
+ function logBytes20(bytes20 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
+ }
+
+ function logBytes21(bytes21 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
+ }
+
+ function logBytes22(bytes22 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
+ }
+
+ function logBytes23(bytes23 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
+ }
+
+ function logBytes24(bytes24 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
+ }
+
+ function logBytes25(bytes25 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
+ }
+
+ function logBytes26(bytes26 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
+ }
+
+ function logBytes27(bytes27 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
+ }
+
+ function logBytes28(bytes28 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
+ }
+
+ function logBytes29(bytes29 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
+ }
+
+ function logBytes30(bytes30 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
+ }
+
+ function logBytes31(bytes31 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
+ }
+
+ function logBytes32(bytes32 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
+ }
+
+ function log(uint256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
+ }
+
+ function log(int256 p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
+ }
+
+ function log(string memory p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string)", p0));
+ }
+
+ function log(bool p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
+ }
+
+ function log(address p0) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address)", p0));
+ }
+
+ function log(uint256 p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
+ }
+
+ function log(uint256 p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
+ }
+
+ function log(uint256 p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
+ }
+
+ function log(uint256 p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
+ }
+
+ function log(string memory p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
+ }
+
+ function log(string memory p0, int256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
+ }
+
+ function log(string memory p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
+ }
+
+ function log(string memory p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
+ }
+
+ function log(string memory p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
+ }
+
+ function log(bool p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
+ }
+
+ function log(bool p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
+ }
+
+ function log(bool p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
+ }
+
+ function log(bool p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
+ }
+
+ function log(address p0, uint256 p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
+ }
+
+ function log(address p0, string memory p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
+ }
+
+ function log(address p0, bool p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
+ }
+
+ function log(address p0, address p1) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
+ }
+
+ function log(string memory p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
+ }
+
+ function log(bool p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, uint256 p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, string memory p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, bool p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, uint256 p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, string memory p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, bool p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
+ }
+
+ function log(address p0, address p1, address p2) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(uint256 p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(string memory p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(bool p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, uint256 p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, string memory p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, bool p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, uint256 p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, string memory p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, bool p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, uint256 p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, string memory p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, bool p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
+ }
+
+ function log(address p0, address p1, address p2, address p3) internal pure {
+ _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/console2.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/console2.sol
new file mode 100644
index 000000000..03531d91d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/console2.sol
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.4.22 <0.9.0;
+
+import {console as console2} from "./console.sol";
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC1155.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC1155.sol
new file mode 100644
index 000000000..f7dd2b410
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC1155.sol
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import "./IERC165.sol";
+
+/// @title ERC-1155 Multi Token Standard
+/// @dev See https://eips.ethereum.org/EIPS/eip-1155
+/// Note: The ERC-165 identifier for this interface is 0xd9b67a26.
+interface IERC1155 is IERC165 {
+ /// @dev
+ /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
+ /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
+ /// - The `_from` argument MUST be the address of the holder whose balance is decreased.
+ /// - The `_to` argument MUST be the address of the recipient whose balance is increased.
+ /// - The `_id` argument MUST be the token type being transferred.
+ /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
+ /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
+ /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
+ event TransferSingle(
+ address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value
+ );
+
+ /// @dev
+ /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
+ /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
+ /// - The `_from` argument MUST be the address of the holder whose balance is decreased.
+ /// - The `_to` argument MUST be the address of the recipient whose balance is increased.
+ /// - The `_ids` argument MUST be the list of tokens being transferred.
+ /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by.
+ /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
+ /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
+ event TransferBatch(
+ address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values
+ );
+
+ /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled).
+ event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
+
+ /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986.
+ /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
+ event URI(string _value, uint256 indexed _id);
+
+ /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
+ /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
+ /// - MUST revert if `_to` is the zero address.
+ /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
+ /// - MUST revert on any other error.
+ /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).
+ /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
+ /// @param _from Source address
+ /// @param _to Target address
+ /// @param _id ID of the token type
+ /// @param _value Transfer amount
+ /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
+ function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
+
+ /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call).
+ /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
+ /// - MUST revert if `_to` is the zero address.
+ /// - MUST revert if length of `_ids` is not the same as length of `_values`.
+ /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
+ /// - MUST revert on any other error.
+ /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).
+ /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
+ /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
+ /// @param _from Source address
+ /// @param _to Target address
+ /// @param _ids IDs of each token type (order and length must match _values array)
+ /// @param _values Transfer amounts per token type (order and length must match _ids array)
+ /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
+ function safeBatchTransferFrom(
+ address _from,
+ address _to,
+ uint256[] calldata _ids,
+ uint256[] calldata _values,
+ bytes calldata _data
+ ) external;
+
+ /// @notice Get the balance of an account's tokens.
+ /// @param _owner The address of the token holder
+ /// @param _id ID of the token
+ /// @return The _owner's balance of the token type requested
+ function balanceOf(address _owner, uint256 _id) external view returns (uint256);
+
+ /// @notice Get the balance of multiple account/token pairs
+ /// @param _owners The addresses of the token holders
+ /// @param _ids ID of the tokens
+ /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair)
+ function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids)
+ external
+ view
+ returns (uint256[] memory);
+
+ /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
+ /// @dev MUST emit the ApprovalForAll event on success.
+ /// @param _operator Address to add to the set of authorized operators
+ /// @param _approved True if the operator is approved, false to revoke approval
+ function setApprovalForAll(address _operator, bool _approved) external;
+
+ /// @notice Queries the approval status of an operator for a given owner.
+ /// @param _owner The owner of the tokens
+ /// @param _operator Address of authorized operator
+ /// @return True if the operator is approved, false if not
+ function isApprovedForAll(address _owner, address _operator) external view returns (bool);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC165.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC165.sol
new file mode 100644
index 000000000..9af4bf800
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC165.sol
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+interface IERC165 {
+ /// @notice Query if a contract implements an interface
+ /// @param interfaceID The interface identifier, as specified in ERC-165
+ /// @dev Interface identification is specified in ERC-165. This function
+ /// uses less than 30,000 gas.
+ /// @return `true` if the contract implements `interfaceID` and
+ /// `interfaceID` is not 0xffffffff, `false` otherwise
+ function supportsInterface(bytes4 interfaceID) external view returns (bool);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC20.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC20.sol
new file mode 100644
index 000000000..ba40806c3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC20.sol
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+/// @dev Interface of the ERC20 standard as defined in the EIP.
+/// @dev This includes the optional name, symbol, and decimals metadata.
+interface IERC20 {
+ /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).
+ event Transfer(address indexed from, address indexed to, uint256 value);
+
+ /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`
+ /// is the new allowance.
+ event Approval(address indexed owner, address indexed spender, uint256 value);
+
+ /// @notice Returns the amount of tokens in existence.
+ function totalSupply() external view returns (uint256);
+
+ /// @notice Returns the amount of tokens owned by `account`.
+ function balanceOf(address account) external view returns (uint256);
+
+ /// @notice Moves `amount` tokens from the caller's account to `to`.
+ function transfer(address to, uint256 amount) external returns (bool);
+
+ /// @notice Returns the remaining number of tokens that `spender` is allowed
+ /// to spend on behalf of `owner`
+ function allowance(address owner, address spender) external view returns (uint256);
+
+ /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
+ /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
+ function approve(address spender, uint256 amount) external returns (bool);
+
+ /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism.
+ /// `amount` is then deducted from the caller's allowance.
+ function transferFrom(address from, address to, uint256 amount) external returns (bool);
+
+ /// @notice Returns the name of the token.
+ function name() external view returns (string memory);
+
+ /// @notice Returns the symbol of the token.
+ function symbol() external view returns (string memory);
+
+ /// @notice Returns the decimals places of the token.
+ function decimals() external view returns (uint8);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC4626.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC4626.sol
new file mode 100644
index 000000000..391eeb4de
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC4626.sol
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import "./IERC20.sol";
+
+/// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in
+/// https://eips.ethereum.org/EIPS/eip-4626
+interface IERC4626 is IERC20 {
+ event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
+
+ event Withdraw(
+ address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
+ );
+
+ /// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
+ /// @dev
+ /// - MUST be an ERC-20 token contract.
+ /// - MUST NOT revert.
+ function asset() external view returns (address assetTokenAddress);
+
+ /// @notice Returns the total amount of the underlying asset that is “managed” by Vault.
+ /// @dev
+ /// - SHOULD include any compounding that occurs from yield.
+ /// - MUST be inclusive of any fees that are charged against assets in the Vault.
+ /// - MUST NOT revert.
+ function totalAssets() external view returns (uint256 totalManagedAssets);
+
+ /// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
+ /// scenario where all the conditions are met.
+ /// @dev
+ /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
+ /// - MUST NOT show any variations depending on the caller.
+ /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
+ /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
+ /// from.
+ function convertToShares(uint256 assets) external view returns (uint256 shares);
+
+ /// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
+ /// scenario where all the conditions are met.
+ /// @dev
+ /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
+ /// - MUST NOT show any variations depending on the caller.
+ /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
+ /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
+ /// from.
+ function convertToAssets(uint256 shares) external view returns (uint256 assets);
+
+ /// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
+ /// through a deposit call.
+ /// @dev
+ /// - MUST return a limited value if receiver is subject to some deposit limit.
+ /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
+ /// - MUST NOT revert.
+ function maxDeposit(address receiver) external view returns (uint256 maxAssets);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
+ /// current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
+ /// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
+ /// in the same transaction.
+ /// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
+ /// deposit would be accepted, regardless if the user has enough tokens approved, etc.
+ /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by depositing.
+ function previewDeposit(uint256 assets) external view returns (uint256 shares);
+
+ /// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
+ /// @dev
+ /// - MUST emit the Deposit event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ /// deposit execution, and are accounted for during deposit.
+ /// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
+ /// approving enough underlying tokens to the Vault contract, etc).
+ ///
+ /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
+ function deposit(uint256 assets, address receiver) external returns (uint256 shares);
+
+ /// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
+ /// @dev
+ /// - MUST return a limited value if receiver is subject to some mint limit.
+ /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
+ /// - MUST NOT revert.
+ function maxMint(address receiver) external view returns (uint256 maxShares);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
+ /// current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
+ /// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
+ /// same transaction.
+ /// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
+ /// would be accepted, regardless if the user has enough tokens approved, etc.
+ /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by minting.
+ function previewMint(uint256 shares) external view returns (uint256 assets);
+
+ /// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
+ /// @dev
+ /// - MUST emit the Deposit event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
+ /// execution, and are accounted for during mint.
+ /// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
+ /// approving enough underlying tokens to the Vault contract, etc).
+ ///
+ /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
+ function mint(uint256 shares, address receiver) external returns (uint256 assets);
+
+ /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
+ /// Vault, through a withdrawal call.
+ /// @dev
+ /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
+ /// - MUST NOT revert.
+ function maxWithdraw(address owner) external view returns (uint256 maxAssets);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
+ /// given current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
+ /// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
+ /// called
+ /// in the same transaction.
+ /// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
+ /// the withdrawal would be accepted, regardless if the user has enough shares, etc.
+ /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by depositing.
+ function previewWithdraw(uint256 assets) external view returns (uint256 shares);
+
+ /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver.
+ /// @dev
+ /// - MUST emit the Withdraw event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ /// withdraw execution, and are accounted for during withdrawal.
+ /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
+ /// not having enough shares, etc).
+ ///
+ /// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
+ /// Those methods should be performed separately.
+ function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
+
+ /// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
+ /// through a redeem call.
+ /// @dev
+ /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
+ /// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
+ /// - MUST NOT revert.
+ function maxRedeem(address owner) external view returns (uint256 maxShares);
+
+ /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
+ /// given current on-chain conditions.
+ /// @dev
+ /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
+ /// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
+ /// same transaction.
+ /// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
+ /// redemption would be accepted, regardless if the user has enough shares, etc.
+ /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
+ /// - MUST NOT revert.
+ ///
+ /// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
+ /// share price or some other type of condition, meaning the depositor will lose assets by redeeming.
+ function previewRedeem(uint256 shares) external view returns (uint256 assets);
+
+ /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver.
+ /// @dev
+ /// - MUST emit the Withdraw event.
+ /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
+ /// redeem execution, and are accounted for during redeem.
+ /// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
+ /// not having enough shares, etc).
+ ///
+ /// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
+ /// Those methods should be performed separately.
+ function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC721.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC721.sol
new file mode 100644
index 000000000..0a16f45cc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IERC721.sol
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2;
+
+import "./IERC165.sol";
+
+/// @title ERC-721 Non-Fungible Token Standard
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
+interface IERC721 is IERC165 {
+ /// @dev This emits when ownership of any NFT changes by any mechanism.
+ /// This event emits when NFTs are created (`from` == 0) and destroyed
+ /// (`to` == 0). Exception: during contract creation, any number of NFTs
+ /// may be created and assigned without emitting Transfer. At the time of
+ /// any transfer, the approved address for that NFT (if any) is reset to none.
+ event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
+
+ /// @dev This emits when the approved address for an NFT is changed or
+ /// reaffirmed. The zero address indicates there is no approved address.
+ /// When a Transfer event emits, this also indicates that the approved
+ /// address for that NFT (if any) is reset to none.
+ event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
+
+ /// @dev This emits when an operator is enabled or disabled for an owner.
+ /// The operator can manage all NFTs of the owner.
+ event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
+
+ /// @notice Count all NFTs assigned to an owner
+ /// @dev NFTs assigned to the zero address are considered invalid, and this
+ /// function throws for queries about the zero address.
+ /// @param _owner An address for whom to query the balance
+ /// @return The number of NFTs owned by `_owner`, possibly zero
+ function balanceOf(address _owner) external view returns (uint256);
+
+ /// @notice Find the owner of an NFT
+ /// @dev NFTs assigned to zero address are considered invalid, and queries
+ /// about them do throw.
+ /// @param _tokenId The identifier for an NFT
+ /// @return The address of the owner of the NFT
+ function ownerOf(uint256 _tokenId) external view returns (address);
+
+ /// @notice Transfers the ownership of an NFT from one address to another address
+ /// @dev Throws unless `msg.sender` is the current owner, an authorized
+ /// operator, or the approved address for this NFT. Throws if `_from` is
+ /// not the current owner. Throws if `_to` is the zero address. Throws if
+ /// `_tokenId` is not a valid NFT. When transfer is complete, this function
+ /// checks if `_to` is a smart contract (code size > 0). If so, it calls
+ /// `onERC721Received` on `_to` and throws if the return value is not
+ /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
+ /// @param _from The current owner of the NFT
+ /// @param _to The new owner
+ /// @param _tokenId The NFT to transfer
+ /// @param data Additional data with no specified format, sent in call to `_to`
+ function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
+
+ /// @notice Transfers the ownership of an NFT from one address to another address
+ /// @dev This works identically to the other function with an extra data parameter,
+ /// except this function just sets data to "".
+ /// @param _from The current owner of the NFT
+ /// @param _to The new owner
+ /// @param _tokenId The NFT to transfer
+ function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
+
+ /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
+ /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
+ /// THEY MAY BE PERMANENTLY LOST
+ /// @dev Throws unless `msg.sender` is the current owner, an authorized
+ /// operator, or the approved address for this NFT. Throws if `_from` is
+ /// not the current owner. Throws if `_to` is the zero address. Throws if
+ /// `_tokenId` is not a valid NFT.
+ /// @param _from The current owner of the NFT
+ /// @param _to The new owner
+ /// @param _tokenId The NFT to transfer
+ function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
+
+ /// @notice Change or reaffirm the approved address for an NFT
+ /// @dev The zero address indicates there is no approved address.
+ /// Throws unless `msg.sender` is the current NFT owner, or an authorized
+ /// operator of the current owner.
+ /// @param _approved The new approved NFT controller
+ /// @param _tokenId The NFT to approve
+ function approve(address _approved, uint256 _tokenId) external payable;
+
+ /// @notice Enable or disable approval for a third party ("operator") to manage
+ /// all of `msg.sender`'s assets
+ /// @dev Emits the ApprovalForAll event. The contract MUST allow
+ /// multiple operators per owner.
+ /// @param _operator Address to add to the set of authorized operators
+ /// @param _approved True if the operator is approved, false to revoke approval
+ function setApprovalForAll(address _operator, bool _approved) external;
+
+ /// @notice Get the approved address for a single NFT
+ /// @dev Throws if `_tokenId` is not a valid NFT.
+ /// @param _tokenId The NFT to find the approved address for
+ /// @return The approved address for this NFT, or the zero address if there is none
+ function getApproved(uint256 _tokenId) external view returns (address);
+
+ /// @notice Query if an address is an authorized operator for another address
+ /// @param _owner The address that owns the NFTs
+ /// @param _operator The address that acts on behalf of the owner
+ /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
+ function isApprovedForAll(address _owner, address _operator) external view returns (bool);
+}
+
+/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
+interface IERC721TokenReceiver {
+ /// @notice Handle the receipt of an NFT
+ /// @dev The ERC721 smart contract calls this function on the recipient
+ /// after a `transfer`. This function MAY throw to revert and reject the
+ /// transfer. Return of other than the magic value MUST result in the
+ /// transaction being reverted.
+ /// Note: the contract address is always the message sender.
+ /// @param _operator The address which called `safeTransferFrom` function
+ /// @param _from The address which previously owned the token
+ /// @param _tokenId The NFT identifier which is being transferred
+ /// @param _data Additional data with no specified format
+ /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
+ /// unless throwing
+ function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data)
+ external
+ returns (bytes4);
+}
+
+/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
+interface IERC721Metadata is IERC721 {
+ /// @notice A descriptive name for a collection of NFTs in this contract
+ function name() external view returns (string memory _name);
+
+ /// @notice An abbreviated name for NFTs in this contract
+ function symbol() external view returns (string memory _symbol);
+
+ /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
+ /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
+ /// 3986. The URI may point to a JSON file that conforms to the "ERC721
+ /// Metadata JSON Schema".
+ function tokenURI(uint256 _tokenId) external view returns (string memory);
+}
+
+/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
+/// @dev See https://eips.ethereum.org/EIPS/eip-721
+/// Note: the ERC-165 identifier for this interface is 0x780e9d63.
+interface IERC721Enumerable is IERC721 {
+ /// @notice Count NFTs tracked by this contract
+ /// @return A count of valid NFTs tracked by this contract, where each one of
+ /// them has an assigned and queryable owner not equal to the zero address
+ function totalSupply() external view returns (uint256);
+
+ /// @notice Enumerate valid NFTs
+ /// @dev Throws if `_index` >= `totalSupply()`.
+ /// @param _index A counter less than `totalSupply()`
+ /// @return The token identifier for the `_index`th NFT,
+ /// (sort order not specified)
+ function tokenByIndex(uint256 _index) external view returns (uint256);
+
+ /// @notice Enumerate NFTs assigned to an owner
+ /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
+ /// `_owner` is the zero address, representing invalid NFTs.
+ /// @param _owner An address where we are interested in NFTs owned by them
+ /// @param _index A counter less than `balanceOf(_owner)`
+ /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
+ /// (sort order not specified)
+ function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IMulticall3.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IMulticall3.sol
new file mode 100644
index 000000000..0d031b71d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/interfaces/IMulticall3.sol
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+interface IMulticall3 {
+ struct Call {
+ address target;
+ bytes callData;
+ }
+
+ struct Call3 {
+ address target;
+ bool allowFailure;
+ bytes callData;
+ }
+
+ struct Call3Value {
+ address target;
+ bool allowFailure;
+ uint256 value;
+ bytes callData;
+ }
+
+ struct Result {
+ bool success;
+ bytes returnData;
+ }
+
+ function aggregate(Call[] calldata calls)
+ external
+ payable
+ returns (uint256 blockNumber, bytes[] memory returnData);
+
+ function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData);
+
+ function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData);
+
+ function blockAndAggregate(Call[] calldata calls)
+ external
+ payable
+ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
+
+ function getBasefee() external view returns (uint256 basefee);
+
+ function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash);
+
+ function getBlockNumber() external view returns (uint256 blockNumber);
+
+ function getChainId() external view returns (uint256 chainid);
+
+ function getCurrentBlockCoinbase() external view returns (address coinbase);
+
+ function getCurrentBlockDifficulty() external view returns (uint256 difficulty);
+
+ function getCurrentBlockGasLimit() external view returns (uint256 gaslimit);
+
+ function getCurrentBlockTimestamp() external view returns (uint256 timestamp);
+
+ function getEthBalance(address addr) external view returns (uint256 balance);
+
+ function getLastBlockHash() external view returns (bytes32 blockHash);
+
+ function tryAggregate(bool requireSuccess, Call[] calldata calls)
+ external
+ payable
+ returns (Result[] memory returnData);
+
+ function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
+ external
+ payable
+ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/mocks/MockERC20.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/mocks/MockERC20.sol
new file mode 100644
index 000000000..2a022fa34
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/mocks/MockERC20.sol
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {IERC20} from "../interfaces/IERC20.sol";
+
+/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production.
+/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol
+contract MockERC20 is IERC20 {
+ /*//////////////////////////////////////////////////////////////
+ METADATA STORAGE
+ //////////////////////////////////////////////////////////////*/
+
+ string internal _name;
+
+ string internal _symbol;
+
+ uint8 internal _decimals;
+
+ function name() external view override returns (string memory) {
+ return _name;
+ }
+
+ function symbol() external view override returns (string memory) {
+ return _symbol;
+ }
+
+ function decimals() external view override returns (uint8) {
+ return _decimals;
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ ERC20 STORAGE
+ //////////////////////////////////////////////////////////////*/
+
+ uint256 internal _totalSupply;
+
+ mapping(address => uint256) internal _balanceOf;
+
+ mapping(address => mapping(address => uint256)) internal _allowance;
+
+ function totalSupply() external view override returns (uint256) {
+ return _totalSupply;
+ }
+
+ function balanceOf(address owner) external view override returns (uint256) {
+ return _balanceOf[owner];
+ }
+
+ function allowance(address owner, address spender) external view override returns (uint256) {
+ return _allowance[owner][spender];
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ EIP-2612 STORAGE
+ //////////////////////////////////////////////////////////////*/
+
+ uint256 internal INITIAL_CHAIN_ID;
+
+ bytes32 internal INITIAL_DOMAIN_SEPARATOR;
+
+ mapping(address => uint256) public nonces;
+
+ /*//////////////////////////////////////////////////////////////
+ INITIALIZE
+ //////////////////////////////////////////////////////////////*/
+
+ /// @dev A bool to track whether the contract has been initialized.
+ bool private initialized;
+
+ /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
+ /// syntaxes, we add an initialization function that can be called only once.
+ function initialize(string memory name_, string memory symbol_, uint8 decimals_) public {
+ require(!initialized, "ALREADY_INITIALIZED");
+
+ _name = name_;
+ _symbol = symbol_;
+ _decimals = decimals_;
+
+ INITIAL_CHAIN_ID = _pureChainId();
+ INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
+
+ initialized = true;
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ ERC20 LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function approve(address spender, uint256 amount) public virtual override returns (bool) {
+ _allowance[msg.sender][spender] = amount;
+
+ emit Approval(msg.sender, spender, amount);
+
+ return true;
+ }
+
+ function transfer(address to, uint256 amount) public virtual override returns (bool) {
+ _balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount);
+ _balanceOf[to] = _add(_balanceOf[to], amount);
+
+ emit Transfer(msg.sender, to, amount);
+
+ return true;
+ }
+
+ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
+ uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals.
+
+ if (allowed != ~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount);
+
+ _balanceOf[from] = _sub(_balanceOf[from], amount);
+ _balanceOf[to] = _add(_balanceOf[to], amount);
+
+ emit Transfer(from, to, amount);
+
+ return true;
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ EIP-2612 LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
+ public
+ virtual
+ {
+ require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
+
+ address recoveredAddress = ecrecover(
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ DOMAIN_SEPARATOR(),
+ keccak256(
+ abi.encode(
+ keccak256(
+ "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
+ ),
+ owner,
+ spender,
+ value,
+ nonces[owner]++,
+ deadline
+ )
+ )
+ )
+ ),
+ v,
+ r,
+ s
+ );
+
+ require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
+
+ _allowance[recoveredAddress][spender] = value;
+
+ emit Approval(owner, spender, value);
+ }
+
+ function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
+ return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
+ }
+
+ function computeDomainSeparator() internal view virtual returns (bytes32) {
+ return keccak256(
+ abi.encode(
+ keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
+ keccak256(bytes(_name)),
+ keccak256("1"),
+ _pureChainId(),
+ address(this)
+ )
+ );
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL MINT/BURN LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function _mint(address to, uint256 amount) internal virtual {
+ _totalSupply = _add(_totalSupply, amount);
+ _balanceOf[to] = _add(_balanceOf[to], amount);
+
+ emit Transfer(address(0), to, amount);
+ }
+
+ function _burn(address from, uint256 amount) internal virtual {
+ _balanceOf[from] = _sub(_balanceOf[from], amount);
+ _totalSupply = _sub(_totalSupply, amount);
+
+ emit Transfer(from, address(0), amount);
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL SAFE MATH LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function _add(uint256 a, uint256 b) internal pure returns (uint256) {
+ uint256 c = a + b;
+ require(c >= a, "ERC20: addition overflow");
+ return c;
+ }
+
+ function _sub(uint256 a, uint256 b) internal pure returns (uint256) {
+ require(a >= b, "ERC20: subtraction underflow");
+ return a - b;
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ HELPERS
+ //////////////////////////////////////////////////////////////*/
+
+ // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no
+ // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We
+ // can't simply access the chain ID in a normal view or pure function because the solc View Pure
+ // Checker changed `chainid` from pure to view in 0.8.0.
+ function _viewChainId() private view returns (uint256 chainId) {
+ // Assembly required since `block.chainid` was introduced in 0.8.0.
+ assembly {
+ chainId := chainid()
+ }
+
+ address(this); // Silence warnings in older Solc versions.
+ }
+
+ function _pureChainId() private pure returns (uint256 chainId) {
+ function() internal view returns (uint256) fnIn = _viewChainId;
+ function() internal pure returns (uint256) pureChainId;
+ assembly {
+ pureChainId := fnIn
+ }
+ chainId = pureChainId();
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/mocks/MockERC721.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/mocks/MockERC721.sol
new file mode 100644
index 000000000..7a4909e58
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/mocks/MockERC721.sol
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+import {IERC721Metadata, IERC721TokenReceiver} from "../interfaces/IERC721.sol";
+
+/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production.
+/// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol
+contract MockERC721 is IERC721Metadata {
+ /*//////////////////////////////////////////////////////////////
+ METADATA STORAGE/LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ string internal _name;
+
+ string internal _symbol;
+
+ function name() external view override returns (string memory) {
+ return _name;
+ }
+
+ function symbol() external view override returns (string memory) {
+ return _symbol;
+ }
+
+ function tokenURI(uint256 id) public view virtual override returns (string memory) {}
+
+ /*//////////////////////////////////////////////////////////////
+ ERC721 BALANCE/OWNER STORAGE
+ //////////////////////////////////////////////////////////////*/
+
+ mapping(uint256 => address) internal _ownerOf;
+
+ mapping(address => uint256) internal _balanceOf;
+
+ function ownerOf(uint256 id) public view virtual override returns (address owner) {
+ require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
+ }
+
+ function balanceOf(address owner) public view virtual override returns (uint256) {
+ require(owner != address(0), "ZERO_ADDRESS");
+
+ return _balanceOf[owner];
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ ERC721 APPROVAL STORAGE
+ //////////////////////////////////////////////////////////////*/
+
+ mapping(uint256 => address) internal _getApproved;
+
+ mapping(address => mapping(address => bool)) internal _isApprovedForAll;
+
+ function getApproved(uint256 id) public view virtual override returns (address) {
+ return _getApproved[id];
+ }
+
+ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
+ return _isApprovedForAll[owner][operator];
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ INITIALIZE
+ //////////////////////////////////////////////////////////////*/
+
+ /// @dev A bool to track whether the contract has been initialized.
+ bool private initialized;
+
+ /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and
+ /// syntaxes, we add an initialization function that can be called only once.
+ function initialize(string memory name_, string memory symbol_) public {
+ require(!initialized, "ALREADY_INITIALIZED");
+
+ _name = name_;
+ _symbol = symbol_;
+
+ initialized = true;
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ ERC721 LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function approve(address spender, uint256 id) public payable virtual override {
+ address owner = _ownerOf[id];
+
+ require(msg.sender == owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
+
+ _getApproved[id] = spender;
+
+ emit Approval(owner, spender, id);
+ }
+
+ function setApprovalForAll(address operator, bool approved) public virtual override {
+ _isApprovedForAll[msg.sender][operator] = approved;
+
+ emit ApprovalForAll(msg.sender, operator, approved);
+ }
+
+ function transferFrom(address from, address to, uint256 id) public payable virtual override {
+ require(from == _ownerOf[id], "WRONG_FROM");
+
+ require(to != address(0), "INVALID_RECIPIENT");
+
+ require(
+ msg.sender == from || _isApprovedForAll[from][msg.sender] || msg.sender == _getApproved[id],
+ "NOT_AUTHORIZED"
+ );
+
+ // Underflow of the sender's balance is impossible because we check for
+ // ownership above and the recipient's balance can't realistically overflow.
+ _balanceOf[from]--;
+
+ _balanceOf[to]++;
+
+ _ownerOf[id] = to;
+
+ delete _getApproved[id];
+
+ emit Transfer(from, to, id);
+ }
+
+ function safeTransferFrom(address from, address to, uint256 id) public payable virtual override {
+ transferFrom(from, to, id);
+
+ require(
+ !_isContract(to)
+ || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "")
+ == IERC721TokenReceiver.onERC721Received.selector,
+ "UNSAFE_RECIPIENT"
+ );
+ }
+
+ function safeTransferFrom(address from, address to, uint256 id, bytes memory data)
+ public
+ payable
+ virtual
+ override
+ {
+ transferFrom(from, to, id);
+
+ require(
+ !_isContract(to)
+ || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data)
+ == IERC721TokenReceiver.onERC721Received.selector,
+ "UNSAFE_RECIPIENT"
+ );
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ ERC165 LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
+ return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165
+ || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721
+ || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL MINT/BURN LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function _mint(address to, uint256 id) internal virtual {
+ require(to != address(0), "INVALID_RECIPIENT");
+
+ require(_ownerOf[id] == address(0), "ALREADY_MINTED");
+
+ // Counter overflow is incredibly unrealistic.
+
+ _balanceOf[to]++;
+
+ _ownerOf[id] = to;
+
+ emit Transfer(address(0), to, id);
+ }
+
+ function _burn(uint256 id) internal virtual {
+ address owner = _ownerOf[id];
+
+ require(owner != address(0), "NOT_MINTED");
+
+ _balanceOf[owner]--;
+
+ delete _ownerOf[id];
+
+ delete _getApproved[id];
+
+ emit Transfer(owner, address(0), id);
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ INTERNAL SAFE MINT LOGIC
+ //////////////////////////////////////////////////////////////*/
+
+ function _safeMint(address to, uint256 id) internal virtual {
+ _mint(to, id);
+
+ require(
+ !_isContract(to)
+ || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "")
+ == IERC721TokenReceiver.onERC721Received.selector,
+ "UNSAFE_RECIPIENT"
+ );
+ }
+
+ function _safeMint(address to, uint256 id, bytes memory data) internal virtual {
+ _mint(to, id);
+
+ require(
+ !_isContract(to)
+ || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data)
+ == IERC721TokenReceiver.onERC721Received.selector,
+ "UNSAFE_RECIPIENT"
+ );
+ }
+
+ /*//////////////////////////////////////////////////////////////
+ HELPERS
+ //////////////////////////////////////////////////////////////*/
+
+ function _isContract(address _addr) private view returns (bool) {
+ uint256 codeLength;
+
+ // Assembly required for versions < 0.8.0 to check extcodesize.
+ assembly {
+ codeLength := extcodesize(_addr)
+ }
+
+ return codeLength > 0;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/safeconsole.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/safeconsole.sol
new file mode 100644
index 000000000..87c475a5b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/src/safeconsole.sol
@@ -0,0 +1,13937 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+/// @author philogy
+/// @dev Code generated automatically by script.
+library safeconsole {
+ uint256 constant CONSOLE_ADDR = 0x000000000000000000000000000000000000000000636F6e736F6c652e6c6f67;
+
+ // Credit to [0age](https://twitter.com/z0age/status/1654922202930888704) and [0xdapper](https://github.com/foundry-rs/forge-std/pull/374)
+ // for the view-to-pure log trick.
+ function _sendLogPayload(uint256 offset, uint256 size) private pure {
+ function(uint256, uint256) internal view fnIn = _sendLogPayloadView;
+ function(uint256, uint256) internal pure pureSendLogPayload;
+ /// @solidity memory-safe-assembly
+ assembly {
+ pureSendLogPayload := fnIn
+ }
+ pureSendLogPayload(offset, size);
+ }
+
+ function _sendLogPayloadView(uint256 offset, uint256 size) private view {
+ /// @solidity memory-safe-assembly
+ assembly {
+ pop(staticcall(gas(), CONSOLE_ADDR, offset, size, 0x0, 0x0))
+ }
+ }
+
+ function _memcopy(uint256 fromOffset, uint256 toOffset, uint256 length) private pure {
+ function(uint256, uint256, uint256) internal view fnIn = _memcopyView;
+ function(uint256, uint256, uint256) internal pure pureMemcopy;
+ /// @solidity memory-safe-assembly
+ assembly {
+ pureMemcopy := fnIn
+ }
+ pureMemcopy(fromOffset, toOffset, length);
+ }
+
+ function _memcopyView(uint256 fromOffset, uint256 toOffset, uint256 length) private view {
+ /// @solidity memory-safe-assembly
+ assembly {
+ pop(staticcall(gas(), 0x4, fromOffset, length, toOffset, length))
+ }
+ }
+
+ function logMemory(uint256 offset, uint256 length) internal pure {
+ if (offset >= 0x60) {
+ // Sufficient memory before slice to prepare call header.
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(sub(offset, 0x60))
+ m1 := mload(sub(offset, 0x40))
+ m2 := mload(sub(offset, 0x20))
+ // Selector of `log(bytes)`.
+ mstore(sub(offset, 0x60), 0x0be77f56)
+ mstore(sub(offset, 0x40), 0x20)
+ mstore(sub(offset, 0x20), length)
+ }
+ _sendLogPayload(offset - 0x44, length + 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(sub(offset, 0x60), m0)
+ mstore(sub(offset, 0x40), m1)
+ mstore(sub(offset, 0x20), m2)
+ }
+ } else {
+ // Insufficient space, so copy slice forward, add header and reverse.
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ uint256 endOffset = offset + length;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(add(endOffset, 0x00))
+ m1 := mload(add(endOffset, 0x20))
+ m2 := mload(add(endOffset, 0x40))
+ }
+ _memcopy(offset, offset + 0x60, length);
+ /// @solidity memory-safe-assembly
+ assembly {
+ // Selector of `log(bytes)`.
+ mstore(add(offset, 0x00), 0x0be77f56)
+ mstore(add(offset, 0x20), 0x20)
+ mstore(add(offset, 0x40), length)
+ }
+ _sendLogPayload(offset + 0x1c, length + 0x44);
+ _memcopy(offset + 0x60, offset, length);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(add(endOffset, 0x00), m0)
+ mstore(add(endOffset, 0x20), m1)
+ mstore(add(endOffset, 0x40), m2)
+ }
+ }
+ }
+
+ function log(address p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ // Selector of `log(address)`.
+ mstore(0x00, 0x2c2ecbc2)
+ mstore(0x20, p0)
+ }
+ _sendLogPayload(0x1c, 0x24);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ }
+ }
+
+ function log(bool p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ // Selector of `log(bool)`.
+ mstore(0x00, 0x32458eed)
+ mstore(0x20, p0)
+ }
+ _sendLogPayload(0x1c, 0x24);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ }
+ }
+
+ function log(uint256 p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ // Selector of `log(uint256)`.
+ mstore(0x00, 0xf82c50f1)
+ mstore(0x20, p0)
+ }
+ _sendLogPayload(0x1c, 0x24);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ }
+ }
+
+ function log(bytes32 p0) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(string)`.
+ mstore(0x00, 0x41304fac)
+ mstore(0x20, 0x20)
+ writeString(0x40, p0)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(address,address)`.
+ mstore(0x00, 0xdaf0d4aa)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(address p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(address,bool)`.
+ mstore(0x00, 0x75b605d3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(address p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(address,uint256)`.
+ mstore(0x00, 0x8309e8a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(address p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,string)`.
+ mstore(0x00, 0x759f86bb)
+ mstore(0x20, p0)
+ mstore(0x40, 0x40)
+ writeString(0x60, p1)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(bool,address)`.
+ mstore(0x00, 0x853c4849)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(bool p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(bool,bool)`.
+ mstore(0x00, 0x2a110e83)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(bool p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(bool,uint256)`.
+ mstore(0x00, 0x399174d3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(bool p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,string)`.
+ mstore(0x00, 0x8feac525)
+ mstore(0x20, p0)
+ mstore(0x40, 0x40)
+ writeString(0x60, p1)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(uint256,address)`.
+ mstore(0x00, 0x69276c86)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(uint256 p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(uint256,bool)`.
+ mstore(0x00, 0x1c9d7eb3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ // Selector of `log(uint256,uint256)`.
+ mstore(0x00, 0xf666715a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ }
+ _sendLogPayload(0x1c, 0x44);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,string)`.
+ mstore(0x00, 0x643fd0df)
+ mstore(0x20, p0)
+ mstore(0x40, 0x40)
+ writeString(0x60, p1)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, address p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(string,address)`.
+ mstore(0x00, 0x319af333)
+ mstore(0x20, 0x40)
+ mstore(0x40, p1)
+ writeString(0x60, p0)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, bool p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(string,bool)`.
+ mstore(0x00, 0xc3b55635)
+ mstore(0x20, 0x40)
+ mstore(0x40, p1)
+ writeString(0x60, p0)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(string,uint256)`.
+ mstore(0x00, 0xb60e72cc)
+ mstore(0x20, 0x40)
+ mstore(0x40, p1)
+ writeString(0x60, p0)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,string)`.
+ mstore(0x00, 0x4b5c4277)
+ mstore(0x20, 0x40)
+ mstore(0x40, 0x80)
+ writeString(0x60, p0)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,address,address)`.
+ mstore(0x00, 0x018c84c2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,address,bool)`.
+ mstore(0x00, 0xf2a66286)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,address,uint256)`.
+ mstore(0x00, 0x17fe6185)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,address,string)`.
+ mstore(0x00, 0x007150be)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,bool,address)`.
+ mstore(0x00, 0xf11699ed)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,bool,bool)`.
+ mstore(0x00, 0xeb830c92)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,bool,uint256)`.
+ mstore(0x00, 0x9c4f99fb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,bool,string)`.
+ mstore(0x00, 0x212255cc)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,uint256,address)`.
+ mstore(0x00, 0x7bc0d848)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,uint256,bool)`.
+ mstore(0x00, 0x678209a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(address,uint256,uint256)`.
+ mstore(0x00, 0xb69bcaf6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,uint256,string)`.
+ mstore(0x00, 0xa1f2e8aa)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,string,address)`.
+ mstore(0x00, 0xf08744e8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,string,bool)`.
+ mstore(0x00, 0xcf020fb1)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(address,string,uint256)`.
+ mstore(0x00, 0x67dd6ff1)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(address,string,string)`.
+ mstore(0x00, 0xfb772265)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p1)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bool p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,address,address)`.
+ mstore(0x00, 0xd2763667)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,address,bool)`.
+ mstore(0x00, 0x18c9c746)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,address,uint256)`.
+ mstore(0x00, 0x5f7b9afb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,address,string)`.
+ mstore(0x00, 0xde9a9270)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,bool,address)`.
+ mstore(0x00, 0x1078f68d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,bool,bool)`.
+ mstore(0x00, 0x50709698)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,bool,uint256)`.
+ mstore(0x00, 0x12f21602)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,bool,string)`.
+ mstore(0x00, 0x2555fa46)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,uint256,address)`.
+ mstore(0x00, 0x088ef9d2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,uint256,bool)`.
+ mstore(0x00, 0xe8defba9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(bool,uint256,uint256)`.
+ mstore(0x00, 0x37103367)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,uint256,string)`.
+ mstore(0x00, 0xc3fc3970)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,string,address)`.
+ mstore(0x00, 0x9591b953)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,string,bool)`.
+ mstore(0x00, 0xdbb4c247)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(bool,string,uint256)`.
+ mstore(0x00, 0x1093ee11)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(bool,string,string)`.
+ mstore(0x00, 0xb076847f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p1)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,address,address)`.
+ mstore(0x00, 0xbcfd9be0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,address,bool)`.
+ mstore(0x00, 0x9b6ec042)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,address,uint256)`.
+ mstore(0x00, 0x5a9b5ed5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,address,string)`.
+ mstore(0x00, 0x63cb41f9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,bool,address)`.
+ mstore(0x00, 0x35085f7b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,bool,bool)`.
+ mstore(0x00, 0x20718650)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,bool,uint256)`.
+ mstore(0x00, 0x20098014)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,bool,string)`.
+ mstore(0x00, 0x85775021)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,uint256,address)`.
+ mstore(0x00, 0x5c96b331)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,uint256,bool)`.
+ mstore(0x00, 0x4766da72)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ // Selector of `log(uint256,uint256,uint256)`.
+ mstore(0x00, 0xd1ed7a3c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ }
+ _sendLogPayload(0x1c, 0x64);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,uint256,string)`.
+ mstore(0x00, 0x71d04af2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x60)
+ writeString(0x80, p2)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,string,address)`.
+ mstore(0x00, 0x7afac959)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,string,bool)`.
+ mstore(0x00, 0x4ceda75a)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(uint256,string,uint256)`.
+ mstore(0x00, 0x37aa7d4c)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, p2)
+ writeString(0x80, p1)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(uint256,string,string)`.
+ mstore(0x00, 0xb115611f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x60)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p1)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,address,address)`.
+ mstore(0x00, 0xfcec75e0)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,address,bool)`.
+ mstore(0x00, 0xc91d5ed4)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,address,uint256)`.
+ mstore(0x00, 0x0d26b925)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,address,string)`.
+ mstore(0x00, 0xe0e9ad4f)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p0)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,bool,address)`.
+ mstore(0x00, 0x932bbb38)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,bool,bool)`.
+ mstore(0x00, 0x850b7ad6)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,bool,uint256)`.
+ mstore(0x00, 0xc95958d6)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,bool,string)`.
+ mstore(0x00, 0xe298f47d)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p0)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,uint256,address)`.
+ mstore(0x00, 0x1c7ec448)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,uint256,bool)`.
+ mstore(0x00, 0xca7733b1)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ // Selector of `log(string,uint256,uint256)`.
+ mstore(0x00, 0xca47c4eb)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ }
+ _sendLogPayload(0x1c, 0xa4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,uint256,string)`.
+ mstore(0x00, 0x5970e089)
+ mstore(0x20, 0x60)
+ mstore(0x40, p1)
+ mstore(0x60, 0xa0)
+ writeString(0x80, p0)
+ writeString(0xc0, p2)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,string,address)`.
+ mstore(0x00, 0x95ed0195)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,string,bool)`.
+ mstore(0x00, 0xb0e0f9b5)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ // Selector of `log(string,string,uint256)`.
+ mstore(0x00, 0x5821efa1)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, p2)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ }
+ _sendLogPayload(0x1c, 0xe4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ // Selector of `log(string,string,string)`.
+ mstore(0x00, 0x2ced7cef)
+ mstore(0x20, 0x60)
+ mstore(0x40, 0xa0)
+ mstore(0x60, 0xe0)
+ writeString(0x80, p0)
+ writeString(0xc0, p1)
+ writeString(0x100, p2)
+ }
+ _sendLogPayload(0x1c, 0x124);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ }
+ }
+
+ function log(address p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,address,address)`.
+ mstore(0x00, 0x665bf134)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,address,bool)`.
+ mstore(0x00, 0x0e378994)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,address,uint256)`.
+ mstore(0x00, 0x94250d77)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,address,string)`.
+ mstore(0x00, 0xf808da20)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,bool,address)`.
+ mstore(0x00, 0x9f1bc36e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,bool,bool)`.
+ mstore(0x00, 0x2cd4134a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,bool,uint256)`.
+ mstore(0x00, 0x3971e78c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,bool,string)`.
+ mstore(0x00, 0xaa6540c8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,uint256,address)`.
+ mstore(0x00, 0x8da6def5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,uint256,bool)`.
+ mstore(0x00, 0x9b4254e2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,address,uint256,uint256)`.
+ mstore(0x00, 0xbe553481)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,uint256,string)`.
+ mstore(0x00, 0xfdb4f990)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,string,address)`.
+ mstore(0x00, 0x8f736d16)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,string,bool)`.
+ mstore(0x00, 0x6f1a594e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,address,string,uint256)`.
+ mstore(0x00, 0xef1cefe7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,address,string,string)`.
+ mstore(0x00, 0x21bdaf25)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,address,address)`.
+ mstore(0x00, 0x660375dd)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,address,bool)`.
+ mstore(0x00, 0xa6f50b0f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,address,uint256)`.
+ mstore(0x00, 0xa75c59de)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,address,string)`.
+ mstore(0x00, 0x2dd778e6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,bool,address)`.
+ mstore(0x00, 0xcf394485)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,bool,bool)`.
+ mstore(0x00, 0xcac43479)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,bool,uint256)`.
+ mstore(0x00, 0x8c4e5de6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,bool,string)`.
+ mstore(0x00, 0xdfc4a2e8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,uint256,address)`.
+ mstore(0x00, 0xccf790a1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,uint256,bool)`.
+ mstore(0x00, 0xc4643e20)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,bool,uint256,uint256)`.
+ mstore(0x00, 0x386ff5f4)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,uint256,string)`.
+ mstore(0x00, 0x0aa6cfad)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,string,address)`.
+ mstore(0x00, 0x19fd4956)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,string,bool)`.
+ mstore(0x00, 0x50ad461d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,bool,string,uint256)`.
+ mstore(0x00, 0x80e6a20b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,bool,string,string)`.
+ mstore(0x00, 0x475c5c33)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,address,address)`.
+ mstore(0x00, 0x478d1c62)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,address,bool)`.
+ mstore(0x00, 0xa1bcc9b3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,address,uint256)`.
+ mstore(0x00, 0x100f650e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,address,string)`.
+ mstore(0x00, 0x1da986ea)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,bool,address)`.
+ mstore(0x00, 0xa31bfdcc)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,bool,bool)`.
+ mstore(0x00, 0x3bf5e537)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,bool,uint256)`.
+ mstore(0x00, 0x22f6b999)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,bool,string)`.
+ mstore(0x00, 0xc5ad85f9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,uint256,address)`.
+ mstore(0x00, 0x20e3984d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,uint256,bool)`.
+ mstore(0x00, 0x66f1bc67)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(address,uint256,uint256,uint256)`.
+ mstore(0x00, 0x34f0e636)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(address p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,uint256,string)`.
+ mstore(0x00, 0x4a28c017)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,string,address)`.
+ mstore(0x00, 0x5c430d47)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,string,bool)`.
+ mstore(0x00, 0xcf18105c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,uint256,string,uint256)`.
+ mstore(0x00, 0xbf01f891)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,uint256,string,string)`.
+ mstore(0x00, 0x88a8c406)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,address,address)`.
+ mstore(0x00, 0x0d36fa20)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,address,bool)`.
+ mstore(0x00, 0x0df12b76)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,address,uint256)`.
+ mstore(0x00, 0x457fe3cf)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,address,string)`.
+ mstore(0x00, 0xf7e36245)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,bool,address)`.
+ mstore(0x00, 0x205871c2)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,bool,bool)`.
+ mstore(0x00, 0x5f1d5c9f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,bool,uint256)`.
+ mstore(0x00, 0x515e38b6)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,bool,string)`.
+ mstore(0x00, 0xbc0b61fe)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,uint256,address)`.
+ mstore(0x00, 0x63183678)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,uint256,bool)`.
+ mstore(0x00, 0x0ef7e050)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(address,string,uint256,uint256)`.
+ mstore(0x00, 0x1dc8e1b8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(address p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,uint256,string)`.
+ mstore(0x00, 0x448830a8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,string,address)`.
+ mstore(0x00, 0xa04e2f87)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,string,bool)`.
+ mstore(0x00, 0x35a5071f)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(address,string,string,uint256)`.
+ mstore(0x00, 0x159f8927)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(address p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(address,string,string,string)`.
+ mstore(0x00, 0x5d02c50b)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,address,address)`.
+ mstore(0x00, 0x1d14d001)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,address,bool)`.
+ mstore(0x00, 0x46600be0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,address,uint256)`.
+ mstore(0x00, 0x0c66d1be)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,address,string)`.
+ mstore(0x00, 0xd812a167)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,bool,address)`.
+ mstore(0x00, 0x1c41a336)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,bool,bool)`.
+ mstore(0x00, 0x6a9c478b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,bool,uint256)`.
+ mstore(0x00, 0x07831502)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,bool,string)`.
+ mstore(0x00, 0x4a66cb34)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,uint256,address)`.
+ mstore(0x00, 0x136b05dd)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,uint256,bool)`.
+ mstore(0x00, 0xd6019f1c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,address,uint256,uint256)`.
+ mstore(0x00, 0x7bf181a1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,uint256,string)`.
+ mstore(0x00, 0x51f09ff8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,string,address)`.
+ mstore(0x00, 0x6f7c603e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,string,bool)`.
+ mstore(0x00, 0xe2bfd60b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,address,string,uint256)`.
+ mstore(0x00, 0xc21f64c7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,address,string,string)`.
+ mstore(0x00, 0xa73c1db6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,address,address)`.
+ mstore(0x00, 0xf4880ea4)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,address,bool)`.
+ mstore(0x00, 0xc0a302d8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,address,uint256)`.
+ mstore(0x00, 0x4c123d57)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,address,string)`.
+ mstore(0x00, 0xa0a47963)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,bool,address)`.
+ mstore(0x00, 0x8c329b1a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,bool,bool)`.
+ mstore(0x00, 0x3b2a5ce0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,bool,uint256)`.
+ mstore(0x00, 0x6d7045c1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,bool,string)`.
+ mstore(0x00, 0x2ae408d4)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,uint256,address)`.
+ mstore(0x00, 0x54a7a9a0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,uint256,bool)`.
+ mstore(0x00, 0x619e4d0e)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,bool,uint256,uint256)`.
+ mstore(0x00, 0x0bb00eab)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,uint256,string)`.
+ mstore(0x00, 0x7dd4d0e0)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,string,address)`.
+ mstore(0x00, 0xf9ad2b89)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,string,bool)`.
+ mstore(0x00, 0xb857163a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,bool,string,uint256)`.
+ mstore(0x00, 0xe3a9ca2f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,bool,string,string)`.
+ mstore(0x00, 0x6d1e8751)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,address,address)`.
+ mstore(0x00, 0x26f560a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,address,bool)`.
+ mstore(0x00, 0xb4c314ff)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,address,uint256)`.
+ mstore(0x00, 0x1537dc87)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,address,string)`.
+ mstore(0x00, 0x1bb3b09a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,bool,address)`.
+ mstore(0x00, 0x9acd3616)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,bool,bool)`.
+ mstore(0x00, 0xceb5f4d7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,bool,uint256)`.
+ mstore(0x00, 0x7f9bbca2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,bool,string)`.
+ mstore(0x00, 0x9143dbb1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,uint256,address)`.
+ mstore(0x00, 0x00dd87b9)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,uint256,bool)`.
+ mstore(0x00, 0xbe984353)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(bool,uint256,uint256,uint256)`.
+ mstore(0x00, 0x374bb4b2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(bool p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,uint256,string)`.
+ mstore(0x00, 0x8e69fb5d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,string,address)`.
+ mstore(0x00, 0xfedd1fff)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,string,bool)`.
+ mstore(0x00, 0xe5e70b2b)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,uint256,string,uint256)`.
+ mstore(0x00, 0x6a1199e2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,uint256,string,string)`.
+ mstore(0x00, 0xf5bc2249)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,address,address)`.
+ mstore(0x00, 0x2b2b18dc)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,address,bool)`.
+ mstore(0x00, 0x6dd434ca)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,address,uint256)`.
+ mstore(0x00, 0xa5cada94)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,address,string)`.
+ mstore(0x00, 0x12d6c788)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,bool,address)`.
+ mstore(0x00, 0x538e06ab)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,bool,bool)`.
+ mstore(0x00, 0xdc5e935b)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,bool,uint256)`.
+ mstore(0x00, 0x1606a393)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,bool,string)`.
+ mstore(0x00, 0x483d0416)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,uint256,address)`.
+ mstore(0x00, 0x1596a1ce)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,uint256,bool)`.
+ mstore(0x00, 0x6b0e5d53)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(bool,string,uint256,uint256)`.
+ mstore(0x00, 0x28863fcb)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,uint256,string)`.
+ mstore(0x00, 0x1ad96de6)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,string,address)`.
+ mstore(0x00, 0x97d394d8)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,string,bool)`.
+ mstore(0x00, 0x1e4b87e5)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(bool,string,string,uint256)`.
+ mstore(0x00, 0x7be0c3eb)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bool p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(bool,string,string,string)`.
+ mstore(0x00, 0x1762e32a)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,address,address)`.
+ mstore(0x00, 0x2488b414)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,address,bool)`.
+ mstore(0x00, 0x091ffaf5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,address,uint256)`.
+ mstore(0x00, 0x736efbb6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,address,string)`.
+ mstore(0x00, 0x031c6f73)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,bool,address)`.
+ mstore(0x00, 0xef72c513)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,bool,bool)`.
+ mstore(0x00, 0xe351140f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,bool,uint256)`.
+ mstore(0x00, 0x5abd992a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,bool,string)`.
+ mstore(0x00, 0x90fb06aa)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,uint256,address)`.
+ mstore(0x00, 0x15c127b5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,uint256,bool)`.
+ mstore(0x00, 0x5f743a7c)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,address,uint256,uint256)`.
+ mstore(0x00, 0x0c9cd9c1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,uint256,string)`.
+ mstore(0x00, 0xddb06521)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,string,address)`.
+ mstore(0x00, 0x9cba8fff)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,string,bool)`.
+ mstore(0x00, 0xcc32ab07)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,address,string,uint256)`.
+ mstore(0x00, 0x46826b5d)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,address,string,string)`.
+ mstore(0x00, 0x3e128ca3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,address,address)`.
+ mstore(0x00, 0xa1ef4cbb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,address,bool)`.
+ mstore(0x00, 0x454d54a5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,address,uint256)`.
+ mstore(0x00, 0x078287f5)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,address,string)`.
+ mstore(0x00, 0xade052c7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,bool,address)`.
+ mstore(0x00, 0x69640b59)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,bool,bool)`.
+ mstore(0x00, 0xb6f577a1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,bool,uint256)`.
+ mstore(0x00, 0x7464ce23)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,bool,string)`.
+ mstore(0x00, 0xdddb9561)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,uint256,address)`.
+ mstore(0x00, 0x88cb6041)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,uint256,bool)`.
+ mstore(0x00, 0x91a02e2a)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,bool,uint256,uint256)`.
+ mstore(0x00, 0xc6acc7a8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,uint256,string)`.
+ mstore(0x00, 0xde03e774)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,string,address)`.
+ mstore(0x00, 0xef529018)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,string,bool)`.
+ mstore(0x00, 0xeb928d7f)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,bool,string,uint256)`.
+ mstore(0x00, 0x2c1d0746)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,bool,string,string)`.
+ mstore(0x00, 0x68c8b8bd)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,address,address)`.
+ mstore(0x00, 0x56a5d1b1)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,address,bool)`.
+ mstore(0x00, 0x15cac476)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,address,uint256)`.
+ mstore(0x00, 0x88f6e4b2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,address,string)`.
+ mstore(0x00, 0x6cde40b8)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,bool,address)`.
+ mstore(0x00, 0x9a816a83)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,bool,bool)`.
+ mstore(0x00, 0xab085ae6)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,bool,uint256)`.
+ mstore(0x00, 0xeb7f6fd2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,bool,string)`.
+ mstore(0x00, 0xa5b4fc99)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,uint256,address)`.
+ mstore(0x00, 0xfa8185af)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,uint256,bool)`.
+ mstore(0x00, 0xc598d185)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ /// @solidity memory-safe-assembly
+ assembly {
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ // Selector of `log(uint256,uint256,uint256,uint256)`.
+ mstore(0x00, 0x193fb800)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ }
+ _sendLogPayload(0x1c, 0x84);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,uint256,string)`.
+ mstore(0x00, 0x59cfcbe3)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0x80)
+ writeString(0xa0, p3)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,string,address)`.
+ mstore(0x00, 0x42d21db7)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,string,bool)`.
+ mstore(0x00, 0x7af6ab25)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,uint256,string,uint256)`.
+ mstore(0x00, 0x5da297eb)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, p3)
+ writeString(0xa0, p2)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,uint256,string,string)`.
+ mstore(0x00, 0x27d8afd2)
+ mstore(0x20, p0)
+ mstore(0x40, p1)
+ mstore(0x60, 0x80)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p2)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,address,address)`.
+ mstore(0x00, 0x6168ed61)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,address,bool)`.
+ mstore(0x00, 0x90c30a56)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,address,uint256)`.
+ mstore(0x00, 0xe8d3018d)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,address,string)`.
+ mstore(0x00, 0x9c3adfa1)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,bool,address)`.
+ mstore(0x00, 0xae2ec581)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,bool,bool)`.
+ mstore(0x00, 0xba535d9c)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,bool,uint256)`.
+ mstore(0x00, 0xcf009880)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,bool,string)`.
+ mstore(0x00, 0xd2d423cd)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,uint256,address)`.
+ mstore(0x00, 0x3b2279b4)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,uint256,bool)`.
+ mstore(0x00, 0x691a8f74)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(uint256,string,uint256,uint256)`.
+ mstore(0x00, 0x82c25b74)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,uint256,string)`.
+ mstore(0x00, 0xb7b914ca)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p1)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,string,address)`.
+ mstore(0x00, 0xd583c602)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,string,bool)`.
+ mstore(0x00, 0xb3a6b6bd)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(uint256,string,string,uint256)`.
+ mstore(0x00, 0xb028c9bd)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(uint256 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(uint256,string,string,string)`.
+ mstore(0x00, 0x21ad0683)
+ mstore(0x20, p0)
+ mstore(0x40, 0x80)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p1)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,address,address)`.
+ mstore(0x00, 0xed8f28f6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,address,bool)`.
+ mstore(0x00, 0xb59dbd60)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,address,uint256)`.
+ mstore(0x00, 0x8ef3f399)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,address,string)`.
+ mstore(0x00, 0x800a1c67)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,bool,address)`.
+ mstore(0x00, 0x223603bd)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,bool,bool)`.
+ mstore(0x00, 0x79884c2b)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,bool,uint256)`.
+ mstore(0x00, 0x3e9f866a)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,bool,string)`.
+ mstore(0x00, 0x0454c079)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,uint256,address)`.
+ mstore(0x00, 0x63fb8bc5)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,uint256,bool)`.
+ mstore(0x00, 0xfc4845f0)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,address,uint256,uint256)`.
+ mstore(0x00, 0xf8f51b1e)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, address p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,uint256,string)`.
+ mstore(0x00, 0x5a477632)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,string,address)`.
+ mstore(0x00, 0xaabc9a31)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,string,bool)`.
+ mstore(0x00, 0x5f15d28c)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,address,string,uint256)`.
+ mstore(0x00, 0x91d1112e)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, address p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,address,string,string)`.
+ mstore(0x00, 0x245986f2)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,address,address)`.
+ mstore(0x00, 0x33e9dd1d)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,address,bool)`.
+ mstore(0x00, 0x958c28c6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,address,uint256)`.
+ mstore(0x00, 0x5d08bb05)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,address,string)`.
+ mstore(0x00, 0x2d8e33a4)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,bool,address)`.
+ mstore(0x00, 0x7190a529)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,bool,bool)`.
+ mstore(0x00, 0x895af8c5)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,bool,uint256)`.
+ mstore(0x00, 0x8e3f78a9)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,bool,string)`.
+ mstore(0x00, 0x9d22d5dd)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,uint256,address)`.
+ mstore(0x00, 0x935e09bf)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,uint256,bool)`.
+ mstore(0x00, 0x8af7cf8a)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,bool,uint256,uint256)`.
+ mstore(0x00, 0x64b5bb67)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,uint256,string)`.
+ mstore(0x00, 0x742d6ee7)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,string,address)`.
+ mstore(0x00, 0xe0625b29)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,string,bool)`.
+ mstore(0x00, 0x3f8a701d)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,bool,string,uint256)`.
+ mstore(0x00, 0x24f91465)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bool p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,bool,string,string)`.
+ mstore(0x00, 0xa826caeb)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,address,address)`.
+ mstore(0x00, 0x5ea2b7ae)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,address,bool)`.
+ mstore(0x00, 0x82112a42)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,address,uint256)`.
+ mstore(0x00, 0x4f04fdc6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,address,string)`.
+ mstore(0x00, 0x9ffb2f93)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,bool,address)`.
+ mstore(0x00, 0xe0e95b98)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,bool,bool)`.
+ mstore(0x00, 0x354c36d6)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,bool,uint256)`.
+ mstore(0x00, 0xe41b6f6f)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,bool,string)`.
+ mstore(0x00, 0xabf73a98)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,uint256,address)`.
+ mstore(0x00, 0xe21de278)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,uint256,bool)`.
+ mstore(0x00, 0x7626db92)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ // Selector of `log(string,uint256,uint256,uint256)`.
+ mstore(0x00, 0xa7a87853)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ }
+ _sendLogPayload(0x1c, 0xc4);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,uint256,string)`.
+ mstore(0x00, 0x854b3496)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, p2)
+ mstore(0x80, 0xc0)
+ writeString(0xa0, p0)
+ writeString(0xe0, p3)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,string,address)`.
+ mstore(0x00, 0x7c4632a4)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,string,bool)`.
+ mstore(0x00, 0x7d24491d)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,uint256,string,uint256)`.
+ mstore(0x00, 0xc67ea9d1)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, uint256 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,uint256,string,string)`.
+ mstore(0x00, 0x5ab84e1f)
+ mstore(0x20, 0x80)
+ mstore(0x40, p1)
+ mstore(0x60, 0xc0)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p2)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,address,address)`.
+ mstore(0x00, 0x439c7bef)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,address,bool)`.
+ mstore(0x00, 0x5ccd4e37)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,address,uint256)`.
+ mstore(0x00, 0x7cc3c607)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, address p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,address,string)`.
+ mstore(0x00, 0xeb1bff80)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,bool,address)`.
+ mstore(0x00, 0xc371c7db)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,bool,bool)`.
+ mstore(0x00, 0x40785869)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,bool,uint256)`.
+ mstore(0x00, 0xd6aefad2)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bool p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,bool,string)`.
+ mstore(0x00, 0x5e84b0ea)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,uint256,address)`.
+ mstore(0x00, 0x1023f7b2)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,uint256,bool)`.
+ mstore(0x00, 0xc3a8a654)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ // Selector of `log(string,string,uint256,uint256)`.
+ mstore(0x00, 0xf45d7d2c)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ }
+ _sendLogPayload(0x1c, 0x104);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, uint256 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,uint256,string)`.
+ mstore(0x00, 0x5d1a971a)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, p2)
+ mstore(0x80, 0x100)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p3)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, address p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,string,address)`.
+ mstore(0x00, 0x6d572f44)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, bool p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,string,bool)`.
+ mstore(0x00, 0x2c1754ed)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, uint256 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ // Selector of `log(string,string,string,uint256)`.
+ mstore(0x00, 0x8eafb02b)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, p3)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ }
+ _sendLogPayload(0x1c, 0x144);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ }
+ }
+
+ function log(bytes32 p0, bytes32 p1, bytes32 p2, bytes32 p3) internal pure {
+ bytes32 m0;
+ bytes32 m1;
+ bytes32 m2;
+ bytes32 m3;
+ bytes32 m4;
+ bytes32 m5;
+ bytes32 m6;
+ bytes32 m7;
+ bytes32 m8;
+ bytes32 m9;
+ bytes32 m10;
+ bytes32 m11;
+ bytes32 m12;
+ /// @solidity memory-safe-assembly
+ assembly {
+ function writeString(pos, w) {
+ let length := 0
+ for {} lt(length, 0x20) { length := add(length, 1) } { if iszero(byte(length, w)) { break } }
+ mstore(pos, length)
+ let shift := sub(256, shl(3, length))
+ mstore(add(pos, 0x20), shl(shift, shr(shift, w)))
+ }
+ m0 := mload(0x00)
+ m1 := mload(0x20)
+ m2 := mload(0x40)
+ m3 := mload(0x60)
+ m4 := mload(0x80)
+ m5 := mload(0xa0)
+ m6 := mload(0xc0)
+ m7 := mload(0xe0)
+ m8 := mload(0x100)
+ m9 := mload(0x120)
+ m10 := mload(0x140)
+ m11 := mload(0x160)
+ m12 := mload(0x180)
+ // Selector of `log(string,string,string,string)`.
+ mstore(0x00, 0xde68f20a)
+ mstore(0x20, 0x80)
+ mstore(0x40, 0xc0)
+ mstore(0x60, 0x100)
+ mstore(0x80, 0x140)
+ writeString(0xa0, p0)
+ writeString(0xe0, p1)
+ writeString(0x120, p2)
+ writeString(0x160, p3)
+ }
+ _sendLogPayload(0x1c, 0x184);
+ /// @solidity memory-safe-assembly
+ assembly {
+ mstore(0x00, m0)
+ mstore(0x20, m1)
+ mstore(0x40, m2)
+ mstore(0x60, m3)
+ mstore(0x80, m4)
+ mstore(0xa0, m5)
+ mstore(0xc0, m6)
+ mstore(0xe0, m7)
+ mstore(0x100, m8)
+ mstore(0x120, m9)
+ mstore(0x140, m10)
+ mstore(0x160, m11)
+ mstore(0x180, m12)
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdAssertions.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdAssertions.t.sol
new file mode 100644
index 000000000..9385a607a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdAssertions.t.sol
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {StdAssertions} from "../src/StdAssertions.sol";
+import {Vm} from "../src/Vm.sol";
+
+interface VmInternal is Vm {
+ function _expectCheatcodeRevert(bytes memory message) external;
+}
+
+contract StdAssertionsTest is StdAssertions {
+ string constant errorMessage = "User provided message";
+ uint256 constant maxDecimals = 77;
+
+ bool constant SHOULD_REVERT = true;
+ bool constant SHOULD_RETURN = false;
+
+ bool constant STRICT_REVERT_DATA = true;
+ bool constant NON_STRICT_REVERT_DATA = false;
+
+ VmInternal constant vm = VmInternal(address(uint160(uint256(keccak256("hevm cheat code")))));
+
+ function testFuzz_AssertEqCall_Return_Pass(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory returnData,
+ bool strictRevertData
+ ) external {
+ address targetA = address(new TestMockCall(returnData, SHOULD_RETURN));
+ address targetB = address(new TestMockCall(returnData, SHOULD_RETURN));
+
+ assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
+ }
+
+ function testFuzz_RevertWhenCalled_AssertEqCall_Return_Fail(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory returnDataA,
+ bytes memory returnDataB,
+ bool strictRevertData
+ ) external {
+ vm.assume(keccak256(returnDataA) != keccak256(returnDataB));
+
+ address targetA = address(new TestMockCall(returnDataA, SHOULD_RETURN));
+ address targetB = address(new TestMockCall(returnDataB, SHOULD_RETURN));
+
+ vm._expectCheatcodeRevert(
+ bytes(
+ string.concat(
+ "Call return data does not match: ", vm.toString(returnDataA), " != ", vm.toString(returnDataB)
+ )
+ )
+ );
+ assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
+ }
+
+ function testFuzz_AssertEqCall_Revert_Pass(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory revertDataA,
+ bytes memory revertDataB
+ ) external {
+ address targetA = address(new TestMockCall(revertDataA, SHOULD_REVERT));
+ address targetB = address(new TestMockCall(revertDataB, SHOULD_REVERT));
+
+ assertEqCall(targetA, callDataA, targetB, callDataB, NON_STRICT_REVERT_DATA);
+ }
+
+ function testFuzz_RevertWhenCalled_AssertEqCall_Revert_Fail(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory revertDataA,
+ bytes memory revertDataB
+ ) external {
+ vm.assume(keccak256(revertDataA) != keccak256(revertDataB));
+
+ address targetA = address(new TestMockCall(revertDataA, SHOULD_REVERT));
+ address targetB = address(new TestMockCall(revertDataB, SHOULD_REVERT));
+
+ vm._expectCheatcodeRevert(
+ bytes(
+ string.concat(
+ "Call revert data does not match: ", vm.toString(revertDataA), " != ", vm.toString(revertDataB)
+ )
+ )
+ );
+ assertEqCall(targetA, callDataA, targetB, callDataB, STRICT_REVERT_DATA);
+ }
+
+ function testFuzz_RevertWhenCalled_AssertEqCall_Fail(
+ bytes memory callDataA,
+ bytes memory callDataB,
+ bytes memory returnDataA,
+ bytes memory returnDataB,
+ bool strictRevertData
+ ) external {
+ address targetA = address(new TestMockCall(returnDataA, SHOULD_RETURN));
+ address targetB = address(new TestMockCall(returnDataB, SHOULD_REVERT));
+
+ vm.expectRevert(bytes("assertion failed"));
+ this.assertEqCallExternal(targetA, callDataA, targetB, callDataB, strictRevertData);
+
+ vm.expectRevert(bytes("assertion failed"));
+ this.assertEqCallExternal(targetB, callDataB, targetA, callDataA, strictRevertData);
+ }
+
+ // Helper function to test outcome of assertEqCall via `expect` cheatcodes
+ function assertEqCallExternal(
+ address targetA,
+ bytes memory callDataA,
+ address targetB,
+ bytes memory callDataB,
+ bool strictRevertData
+ ) public {
+ assertEqCall(targetA, callDataA, targetB, callDataB, strictRevertData);
+ }
+
+ function testFailFail() public {
+ fail();
+ }
+}
+
+contract TestMockCall {
+ bytes returnData;
+ bool shouldRevert;
+
+ constructor(bytes memory returnData_, bool shouldRevert_) {
+ returnData = returnData_;
+ shouldRevert = shouldRevert_;
+ }
+
+ fallback() external payable {
+ bytes memory returnData_ = returnData;
+
+ if (shouldRevert) {
+ assembly {
+ revert(add(returnData_, 0x20), mload(returnData_))
+ }
+ } else {
+ assembly {
+ return(add(returnData_, 0x20), mload(returnData_))
+ }
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdChains.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdChains.t.sol
new file mode 100644
index 000000000..48130da5c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdChains.t.sol
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test} from "../src/Test.sol";
+
+contract StdChainsMock is Test {
+ function exposed_getChain(string memory chainAlias) public returns (Chain memory) {
+ return getChain(chainAlias);
+ }
+
+ function exposed_getChain(uint256 chainId) public returns (Chain memory) {
+ return getChain(chainId);
+ }
+
+ function exposed_setChain(string memory chainAlias, ChainData memory chainData) public {
+ setChain(chainAlias, chainData);
+ }
+
+ function exposed_setFallbackToDefaultRpcUrls(bool useDefault) public {
+ setFallbackToDefaultRpcUrls(useDefault);
+ }
+}
+
+contract StdChainsTest is Test {
+ function test_ChainRpcInitialization() public {
+ // RPCs specified in `foundry.toml` should be updated.
+ assertEq(getChain(1).rpcUrl, "https://eth-mainnet.alchemyapi.io/v2/WV407BEiBmjNJfKo9Uo_55u0z0ITyCOX");
+ assertEq(getChain("optimism_sepolia").rpcUrl, "https://sepolia.optimism.io/");
+ assertEq(getChain("arbitrum_one_sepolia").rpcUrl, "https://sepolia-rollup.arbitrum.io/rpc/");
+
+ // Environment variables should be the next fallback
+ assertEq(getChain("arbitrum_nova").rpcUrl, "https://nova.arbitrum.io/rpc");
+ vm.setEnv("ARBITRUM_NOVA_RPC_URL", "myoverride");
+ assertEq(getChain("arbitrum_nova").rpcUrl, "myoverride");
+ vm.setEnv("ARBITRUM_NOVA_RPC_URL", "https://nova.arbitrum.io/rpc");
+
+ // Cannot override RPCs defined in `foundry.toml`
+ vm.setEnv("MAINNET_RPC_URL", "myoverride2");
+ assertEq(getChain("mainnet").rpcUrl, "https://eth-mainnet.alchemyapi.io/v2/WV407BEiBmjNJfKo9Uo_55u0z0ITyCOX");
+
+ // Other RPCs should remain unchanged.
+ assertEq(getChain(31337).rpcUrl, "http://127.0.0.1:8545");
+ assertEq(getChain("sepolia").rpcUrl, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001");
+ }
+
+ // Named with a leading underscore to clarify this is not intended to be run as a normal test,
+ // and is intended to be used in the below `test_Rpcs` test.
+ function _testRpc(string memory rpcAlias) internal {
+ string memory rpcUrl = getChain(rpcAlias).rpcUrl;
+ vm.createSelectFork(rpcUrl);
+ }
+
+ // Ensure we can connect to the default RPC URL for each chain.
+ // Currently commented out since this is slow and public RPCs are flaky, often resulting in failing CI.
+ // function test_Rpcs() public {
+ // _testRpc("mainnet");
+ // _testRpc("sepolia");
+ // _testRpc("holesky");
+ // _testRpc("optimism");
+ // _testRpc("optimism_sepolia");
+ // _testRpc("arbitrum_one");
+ // _testRpc("arbitrum_one_sepolia");
+ // _testRpc("arbitrum_nova");
+ // _testRpc("polygon");
+ // _testRpc("polygon_amoy");
+ // _testRpc("avalanche");
+ // _testRpc("avalanche_fuji");
+ // _testRpc("bnb_smart_chain");
+ // _testRpc("bnb_smart_chain_testnet");
+ // _testRpc("gnosis_chain");
+ // _testRpc("moonbeam");
+ // _testRpc("moonriver");
+ // _testRpc("moonbase");
+ // _testRpc("base_sepolia");
+ // _testRpc("base");
+ // _testRpc("blast_sepolia");
+ // _testRpc("blast");
+ // _testRpc("fantom_opera");
+ // _testRpc("fantom_opera_testnet");
+ // _testRpc("fraxtal");
+ // _testRpc("fraxtal_testnet");
+ // _testRpc("berachain_bartio_testnet");
+ // _testRpc("flare");
+ // _testRpc("flare_coston2");
+ // }
+
+ function test_RevertIf_ChainNotFound() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(string): Chain with alias \"does_not_exist\" not found.");
+ stdChainsMock.exposed_getChain("does_not_exist");
+ }
+
+ function test_RevertIf_SetChain_ChainIdExist_FirstTest() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains setChain(string,ChainData): Chain ID 31337 already used by \"anvil\".");
+ stdChainsMock.exposed_setChain("anvil2", ChainData("Anvil", 31337, "URL"));
+ }
+
+ function test_RevertIf_ChainBubbleUp() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ stdChainsMock.exposed_setChain("needs_undefined_env_var", ChainData("", 123456789, ""));
+ vm.expectRevert(
+ "Failed to resolve env var `UNDEFINED_RPC_URL_PLACEHOLDER` in `${UNDEFINED_RPC_URL_PLACEHOLDER}`: environment variable not found"
+ );
+ stdChainsMock.exposed_getChain("needs_undefined_env_var");
+ }
+
+ function test_RevertIf_SetChain_ChainIdExists_SecondTest() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ stdChainsMock.exposed_setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
+
+ vm.expectRevert('StdChains setChain(string,ChainData): Chain ID 123456789 already used by "custom_chain".');
+
+ stdChainsMock.exposed_setChain("another_custom_chain", ChainData("", 123456789, ""));
+ }
+
+ function test_SetChain() public {
+ setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
+ Chain memory customChain = getChain("custom_chain");
+ assertEq(customChain.name, "Custom Chain");
+ assertEq(customChain.chainId, 123456789);
+ assertEq(customChain.chainAlias, "custom_chain");
+ assertEq(customChain.rpcUrl, "https://custom.chain/");
+ Chain memory chainById = getChain(123456789);
+ assertEq(chainById.name, customChain.name);
+ assertEq(chainById.chainId, customChain.chainId);
+ assertEq(chainById.chainAlias, customChain.chainAlias);
+ assertEq(chainById.rpcUrl, customChain.rpcUrl);
+ customChain.name = "Another Custom Chain";
+ customChain.chainId = 987654321;
+ setChain("another_custom_chain", customChain);
+ Chain memory anotherCustomChain = getChain("another_custom_chain");
+ assertEq(anotherCustomChain.name, "Another Custom Chain");
+ assertEq(anotherCustomChain.chainId, 987654321);
+ assertEq(anotherCustomChain.chainAlias, "another_custom_chain");
+ assertEq(anotherCustomChain.rpcUrl, "https://custom.chain/");
+ // Verify the first chain data was not overwritten
+ chainById = getChain(123456789);
+ assertEq(chainById.name, "Custom Chain");
+ assertEq(chainById.chainId, 123456789);
+ }
+
+ function test_RevertIf_SetEmptyAlias() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains setChain(string,ChainData): Chain alias cannot be the empty string.");
+ stdChainsMock.exposed_setChain("", ChainData("", 123456789, ""));
+ }
+
+ function test_RevertIf_SetNoChainId0() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains setChain(string,ChainData): Chain ID cannot be 0.");
+ stdChainsMock.exposed_setChain("alias", ChainData("", 0, ""));
+ }
+
+ function test_RevertIf_GetNoChainId0() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(uint256): Chain ID cannot be 0.");
+ stdChainsMock.exposed_getChain(0);
+ }
+
+ function test_RevertIf_GetNoEmptyAlias() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(string): Chain alias cannot be the empty string.");
+ stdChainsMock.exposed_getChain("");
+ }
+
+ function test_RevertIf_ChainIdNotFound() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(string): Chain with alias \"no_such_alias\" not found.");
+ stdChainsMock.exposed_getChain("no_such_alias");
+ }
+
+ function test_RevertIf_ChainAliasNotFound() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ vm.expectRevert("StdChains getChain(uint256): Chain with ID 321 not found.");
+
+ stdChainsMock.exposed_getChain(321);
+ }
+
+ function test_SetChain_ExistingOne() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/"));
+ assertEq(getChain(123456789).chainId, 123456789);
+
+ setChain("custom_chain", ChainData("Modified Chain", 999999999, "https://modified.chain/"));
+ vm.expectRevert("StdChains getChain(uint256): Chain with ID 123456789 not found.");
+ stdChainsMock.exposed_getChain(123456789);
+
+ Chain memory modifiedChain = getChain(999999999);
+ assertEq(modifiedChain.name, "Modified Chain");
+ assertEq(modifiedChain.chainId, 999999999);
+ assertEq(modifiedChain.rpcUrl, "https://modified.chain/");
+ }
+
+ function test_RevertIf_DontUseDefaultRpcUrl() public {
+ // We deploy a mock to properly test the revert.
+ StdChainsMock stdChainsMock = new StdChainsMock();
+
+ // Should error if default RPCs flag is set to false.
+ stdChainsMock.exposed_setFallbackToDefaultRpcUrls(false);
+ vm.expectRevert();
+ stdChainsMock.exposed_getChain(31337);
+ vm.expectRevert();
+ stdChainsMock.exposed_getChain("sepolia");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdCheats.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdCheats.t.sol
new file mode 100644
index 000000000..0a5a83237
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdCheats.t.sol
@@ -0,0 +1,618 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {StdCheats} from "../src/StdCheats.sol";
+import {Test} from "../src/Test.sol";
+import {stdJson} from "../src/StdJson.sol";
+import {stdToml} from "../src/StdToml.sol";
+import {IERC20} from "../src/interfaces/IERC20.sol";
+
+contract StdCheatsTest is Test {
+ Bar test;
+
+ using stdJson for string;
+
+ function setUp() public {
+ test = new Bar();
+ }
+
+ function test_Skip() public {
+ vm.warp(100);
+ skip(25);
+ assertEq(block.timestamp, 125);
+ }
+
+ function test_Rewind() public {
+ vm.warp(100);
+ rewind(25);
+ assertEq(block.timestamp, 75);
+ }
+
+ function test_Hoax() public {
+ hoax(address(1337));
+ test.bar{value: 100}(address(1337));
+ }
+
+ function test_HoaxOrigin() public {
+ hoax(address(1337), address(1337));
+ test.origin{value: 100}(address(1337));
+ }
+
+ function test_HoaxDifferentAddresses() public {
+ hoax(address(1337), address(7331));
+ test.origin{value: 100}(address(1337), address(7331));
+ }
+
+ function test_StartHoax() public {
+ startHoax(address(1337));
+ test.bar{value: 100}(address(1337));
+ test.bar{value: 100}(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+
+ function test_StartHoaxOrigin() public {
+ startHoax(address(1337), address(1337));
+ test.origin{value: 100}(address(1337));
+ test.origin{value: 100}(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+
+ function test_ChangePrankMsgSender() public {
+ vm.startPrank(address(1337));
+ test.bar(address(1337));
+ changePrank(address(0xdead));
+ test.bar(address(0xdead));
+ changePrank(address(1337));
+ test.bar(address(1337));
+ vm.stopPrank();
+ }
+
+ function test_ChangePrankMsgSenderAndTxOrigin() public {
+ vm.startPrank(address(1337), address(1338));
+ test.origin(address(1337), address(1338));
+ changePrank(address(0xdead), address(0xbeef));
+ test.origin(address(0xdead), address(0xbeef));
+ changePrank(address(1337), address(1338));
+ test.origin(address(1337), address(1338));
+ vm.stopPrank();
+ }
+
+ function test_MakeAccountEquivalence() public {
+ Account memory account = makeAccount("1337");
+ (address addr, uint256 key) = makeAddrAndKey("1337");
+ assertEq(account.addr, addr);
+ assertEq(account.key, key);
+ }
+
+ function test_MakeAddrEquivalence() public {
+ (address addr,) = makeAddrAndKey("1337");
+ assertEq(makeAddr("1337"), addr);
+ }
+
+ function test_MakeAddrSigning() public {
+ (address addr, uint256 key) = makeAddrAndKey("1337");
+ bytes32 hash = keccak256("some_message");
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash);
+ assertEq(ecrecover(hash, v, r, s), addr);
+ }
+
+ function test_Deal() public {
+ deal(address(this), 1 ether);
+ assertEq(address(this).balance, 1 ether);
+ }
+
+ function test_DealToken() public {
+ Bar barToken = new Bar();
+ address bar = address(barToken);
+ deal(bar, address(this), 10000e18);
+ assertEq(barToken.balanceOf(address(this)), 10000e18);
+ }
+
+ function test_DealTokenAdjustTotalSupply() public {
+ Bar barToken = new Bar();
+ address bar = address(barToken);
+ deal(bar, address(this), 10000e18, true);
+ assertEq(barToken.balanceOf(address(this)), 10000e18);
+ assertEq(barToken.totalSupply(), 20000e18);
+ deal(bar, address(this), 0, true);
+ assertEq(barToken.balanceOf(address(this)), 0);
+ assertEq(barToken.totalSupply(), 10000e18);
+ }
+
+ function test_DealERC1155Token() public {
+ BarERC1155 barToken = new BarERC1155();
+ address bar = address(barToken);
+ dealERC1155(bar, address(this), 0, 10000e18, false);
+ assertEq(barToken.balanceOf(address(this), 0), 10000e18);
+ }
+
+ function test_DealERC1155TokenAdjustTotalSupply() public {
+ BarERC1155 barToken = new BarERC1155();
+ address bar = address(barToken);
+ dealERC1155(bar, address(this), 0, 10000e18, true);
+ assertEq(barToken.balanceOf(address(this), 0), 10000e18);
+ assertEq(barToken.totalSupply(0), 20000e18);
+ dealERC1155(bar, address(this), 0, 0, true);
+ assertEq(barToken.balanceOf(address(this), 0), 0);
+ assertEq(barToken.totalSupply(0), 10000e18);
+ }
+
+ function test_DealERC721Token() public {
+ BarERC721 barToken = new BarERC721();
+ address bar = address(barToken);
+ dealERC721(bar, address(2), 1);
+ assertEq(barToken.balanceOf(address(2)), 1);
+ assertEq(barToken.balanceOf(address(1)), 0);
+ dealERC721(bar, address(1), 2);
+ assertEq(barToken.balanceOf(address(1)), 1);
+ assertEq(barToken.balanceOf(bar), 1);
+ }
+
+ function test_DeployCode() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""));
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ }
+
+ function test_DestroyAccount() public {
+ // deploy something to destroy it
+ BarERC721 barToken = new BarERC721();
+ address bar = address(barToken);
+ vm.setNonce(bar, 10);
+ deal(bar, 100);
+
+ uint256 prevThisBalance = address(this).balance;
+ uint256 size;
+ assembly {
+ size := extcodesize(bar)
+ }
+
+ assertGt(size, 0);
+ assertEq(bar.balance, 100);
+ assertEq(vm.getNonce(bar), 10);
+
+ destroyAccount(bar, address(this));
+ assembly {
+ size := extcodesize(bar)
+ }
+ assertEq(address(this).balance, prevThisBalance + 100);
+ assertEq(vm.getNonce(bar), 0);
+ assertEq(size, 0);
+ assertEq(bar.balance, 0);
+ }
+
+ function test_DeployCodeNoArgs() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar");
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ }
+
+ function test_DeployCodeVal() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar", bytes(""), 1 ether);
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ assertEq(deployed.balance, 1 ether);
+ }
+
+ function test_DeployCodeValNoArgs() public {
+ address deployed = deployCode("StdCheats.t.sol:Bar", 1 ether);
+ assertEq(string(getCode(deployed)), string(getCode(address(test))));
+ assertEq(deployed.balance, 1 ether);
+ }
+
+ // We need this so we can call "this.deployCode" rather than "deployCode" directly
+ function deployCodeHelper(string memory what) external {
+ deployCode(what);
+ }
+
+ function test_RevertIf_DeployCodeFail() public {
+ vm.expectRevert(bytes("StdCheats deployCode(string): Deployment failed."));
+ this.deployCodeHelper("StdCheats.t.sol:RevertingContract");
+ }
+
+ function getCode(address who) internal view returns (bytes memory o_code) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ // retrieve the size of the code, this needs assembly
+ let size := extcodesize(who)
+ // allocate output byte array - this could also be done without assembly
+ // by using o_code = new bytes(size)
+ o_code := mload(0x40)
+ // new "memory end" including padding
+ mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
+ // store length in memory
+ mstore(o_code, size)
+ // actually retrieve the code, this needs assembly
+ extcodecopy(who, add(o_code, 0x20), 0, size)
+ }
+ }
+
+ function test_DeriveRememberKey() public {
+ string memory mnemonic = "test test test test test test test test test test test junk";
+
+ (address deployer, uint256 privateKey) = deriveRememberKey(mnemonic, 0);
+ assertEq(deployer, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
+ assertEq(privateKey, 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80);
+ }
+
+ function test_BytesToUint() public pure {
+ assertEq(3, bytesToUint_test(hex"03"));
+ assertEq(2, bytesToUint_test(hex"02"));
+ assertEq(255, bytesToUint_test(hex"ff"));
+ assertEq(29625, bytesToUint_test(hex"73b9"));
+ }
+
+ function test_ParseJsonTxDetail() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ string memory json = vm.readFile(path);
+ bytes memory transactionDetails = json.parseRaw(".transactions[0].tx");
+ RawTx1559Detail memory rawTxDetail = abi.decode(transactionDetails, (RawTx1559Detail));
+ Tx1559Detail memory txDetail = rawToConvertedEIP1559Detail(rawTxDetail);
+ assertEq(txDetail.from, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
+ assertEq(txDetail.to, 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512);
+ assertEq(
+ txDetail.data,
+ hex"23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004"
+ );
+ assertEq(txDetail.nonce, 3);
+ assertEq(txDetail.txType, 2);
+ assertEq(txDetail.gas, 29625);
+ assertEq(txDetail.value, 0);
+ }
+
+ function test_ReadEIP1559Transaction() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ uint256 index = 0;
+ Tx1559 memory transaction = readTx1559(path, index);
+ transaction;
+ }
+
+ function test_ReadEIP1559Transactions() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ Tx1559[] memory transactions = readTx1559s(path);
+ transactions;
+ }
+
+ function test_ReadReceipt() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ uint256 index = 5;
+ Receipt memory receipt = readReceipt(path, index);
+ assertEq(
+ receipt.logsBloom,
+ hex"00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100"
+ );
+ }
+
+ function test_ReadReceipts() public view {
+ string memory root = vm.projectRoot();
+ string memory path = string.concat(root, "/test/fixtures/broadcast.log.json");
+ Receipt[] memory receipts = readReceipts(path);
+ receipts;
+ }
+
+ function test_GasMeteringModifier() public {
+ uint256 gas_start_normal = gasleft();
+ addInLoop();
+ uint256 gas_used_normal = gas_start_normal - gasleft();
+
+ uint256 gas_start_single = gasleft();
+ addInLoopNoGas();
+ uint256 gas_used_single = gas_start_single - gasleft();
+
+ uint256 gas_start_double = gasleft();
+ addInLoopNoGasNoGas();
+ uint256 gas_used_double = gas_start_double - gasleft();
+
+ assertTrue(gas_used_double + gas_used_single < gas_used_normal);
+ }
+
+ function addInLoop() internal pure returns (uint256) {
+ uint256 b;
+ for (uint256 i; i < 10000; i++) {
+ b += i;
+ }
+ return b;
+ }
+
+ function addInLoopNoGas() internal noGasMetering returns (uint256) {
+ return addInLoop();
+ }
+
+ function addInLoopNoGasNoGas() internal noGasMetering returns (uint256) {
+ return addInLoopNoGas();
+ }
+
+ function bytesToUint_test(bytes memory b) private pure returns (uint256) {
+ uint256 number;
+ for (uint256 i = 0; i < b.length; i++) {
+ number = number + uint256(uint8(b[i])) * (2 ** (8 * (b.length - (i + 1))));
+ }
+ return number;
+ }
+
+ function testFuzz_AssumeAddressIsNot(address addr) external {
+ // skip over Payable and NonPayable enums
+ for (uint8 i = 2; i < uint8(type(AddressType).max); i++) {
+ assumeAddressIsNot(addr, AddressType(i));
+ }
+ assertTrue(addr != address(0));
+ assertTrue(addr < address(1) || addr > address(9));
+ assertTrue(addr != address(vm) || addr != 0x000000000000000000636F6e736F6c652e6c6f67);
+ }
+
+ function test_AssumePayable() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+
+ // all should revert since these addresses are not payable
+
+ // VM address
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumePayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
+
+ // Console address
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumePayable(0x000000000000000000636F6e736F6c652e6c6f67);
+
+ // Create2Deployer
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumePayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
+
+ // all should pass since these addresses are payable
+
+ // vitalik.eth
+ stdCheatsMock.exposed_assumePayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);
+
+ // mock payable contract
+ MockContractPayable cp = new MockContractPayable();
+ stdCheatsMock.exposed_assumePayable(address(cp));
+ }
+
+ function test_AssumeNotPayable() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+
+ // all should pass since these addresses are not payable
+
+ // VM address
+ stdCheatsMock.exposed_assumeNotPayable(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
+
+ // Console address
+ stdCheatsMock.exposed_assumeNotPayable(0x000000000000000000636F6e736F6c652e6c6f67);
+
+ // Create2Deployer
+ stdCheatsMock.exposed_assumeNotPayable(0x4e59b44847b379578588920cA78FbF26c0B4956C);
+
+ // all should revert since these addresses are payable
+
+ // vitalik.eth
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotPayable(0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045);
+
+ // mock payable contract
+ MockContractPayable cp = new MockContractPayable();
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotPayable(address(cp));
+ }
+
+ function testFuzz_AssumeNotPrecompile(address addr) external {
+ assumeNotPrecompile(addr, getChain("optimism_sepolia").chainId);
+ assertTrue(
+ addr < address(1) || (addr > address(9) && addr < address(0x4200000000000000000000000000000000000000))
+ || addr > address(0x4200000000000000000000000000000000000800)
+ );
+ }
+
+ function testFuzz_AssumeNotForgeAddress(address addr) external pure {
+ assumeNotForgeAddress(addr);
+ assertTrue(
+ addr != address(vm) && addr != 0x000000000000000000636F6e736F6c652e6c6f67
+ && addr != 0x4e59b44847b379578588920cA78FbF26c0B4956C
+ );
+ }
+
+ function test_RevertIf_CannotDeployCodeTo() external {
+ vm.expectRevert("StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
+ this._revertDeployCodeTo();
+ }
+
+ function _revertDeployCodeTo() external {
+ deployCodeTo("StdCheats.t.sol:RevertingContract", address(0));
+ }
+
+ function test_DeployCodeTo() external {
+ address arbitraryAddress = makeAddr("arbitraryAddress");
+
+ deployCodeTo(
+ "StdCheats.t.sol:MockContractWithConstructorArgs",
+ abi.encode(uint256(6), true, bytes20(arbitraryAddress)),
+ 1 ether,
+ arbitraryAddress
+ );
+
+ MockContractWithConstructorArgs ct = MockContractWithConstructorArgs(arbitraryAddress);
+
+ assertEq(arbitraryAddress.balance, 1 ether);
+ assertEq(ct.x(), 6);
+ assertTrue(ct.y());
+ assertEq(ct.z(), bytes20(arbitraryAddress));
+ }
+}
+
+contract StdCheatsMock is StdCheats {
+ function exposed_assumePayable(address addr) external {
+ assumePayable(addr);
+ }
+
+ function exposed_assumeNotPayable(address addr) external {
+ assumeNotPayable(addr);
+ }
+
+ // We deploy a mock version so we can properly test expected reverts.
+ function exposed_assumeNotBlacklisted(address token, address addr) external view {
+ return assumeNotBlacklisted(token, addr);
+ }
+}
+
+contract StdCheatsForkTest is Test {
+ address internal constant SHIB = 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE;
+ address internal constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
+ address internal constant USDC_BLACKLISTED_USER = 0x1E34A77868E19A6647b1f2F47B51ed72dEDE95DD;
+ address internal constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
+ address internal constant USDT_BLACKLISTED_USER = 0x8f8a8F4B54a2aAC7799d7bc81368aC27b852822A;
+
+ function setUp() public {
+ // All tests of the `assumeNotBlacklisted` method are fork tests using live contracts.
+ vm.createSelectFork({urlOrAlias: "mainnet", blockNumber: 16_428_900});
+ }
+
+ function test_RevertIf_CannotAssumeNoBlacklisted_EOA() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+ address eoa = vm.addr({privateKey: 1});
+ vm.expectRevert("StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
+ stdCheatsMock.exposed_assumeNotBlacklisted(eoa, address(0));
+ }
+
+ function testFuzz_AssumeNotBlacklisted_TokenWithoutBlacklist(address addr) external view {
+ assumeNotBlacklisted(SHIB, addr);
+ assertTrue(true);
+ }
+
+ function test_RevertIf_AssumeNoBlacklisted_USDC() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotBlacklisted(USDC, USDC_BLACKLISTED_USER);
+ }
+
+ function testFuzz_AssumeNotBlacklisted_USDC(address addr) external view {
+ assumeNotBlacklisted(USDC, addr);
+ assertFalse(USDCLike(USDC).isBlacklisted(addr));
+ }
+
+ function test_RevertIf_AssumeNoBlacklisted_USDT() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdCheatsMock stdCheatsMock = new StdCheatsMock();
+ vm.expectRevert();
+ stdCheatsMock.exposed_assumeNotBlacklisted(USDT, USDT_BLACKLISTED_USER);
+ }
+
+ function testFuzz_AssumeNotBlacklisted_USDT(address addr) external view {
+ assumeNotBlacklisted(USDT, addr);
+ assertFalse(USDTLike(USDT).isBlackListed(addr));
+ }
+
+ function test_dealUSDC() external {
+ // roll fork to the point when USDC contract updated to store balance in packed slots
+ vm.rollFork(19279215);
+
+ uint256 balance = 100e6;
+ deal(USDC, address(this), balance);
+ assertEq(IERC20(USDC).balanceOf(address(this)), balance);
+ }
+}
+
+contract Bar {
+ constructor() payable {
+ /// `DEAL` STDCHEAT
+ totalSupply = 10000e18;
+ balanceOf[address(this)] = totalSupply;
+ }
+
+ /// `HOAX` and `CHANGEPRANK` STDCHEATS
+ function bar(address expectedSender) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ }
+
+ function origin(address expectedSender) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ require(tx.origin == expectedSender, "!prank");
+ }
+
+ function origin(address expectedSender, address expectedOrigin) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ require(tx.origin == expectedOrigin, "!prank");
+ }
+
+ /// `DEAL` STDCHEAT
+ mapping(address => uint256) public balanceOf;
+ uint256 public totalSupply;
+}
+
+contract BarERC1155 {
+ constructor() payable {
+ /// `DEALERC1155` STDCHEAT
+ _totalSupply[0] = 10000e18;
+ _balances[0][address(this)] = _totalSupply[0];
+ }
+
+ function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
+ return _balances[id][account];
+ }
+
+ function totalSupply(uint256 id) public view virtual returns (uint256) {
+ return _totalSupply[id];
+ }
+
+ /// `DEALERC1155` STDCHEAT
+ mapping(uint256 => mapping(address => uint256)) private _balances;
+ mapping(uint256 => uint256) private _totalSupply;
+}
+
+contract BarERC721 {
+ constructor() payable {
+ /// `DEALERC721` STDCHEAT
+ _owners[1] = address(1);
+ _balances[address(1)] = 1;
+ _owners[2] = address(this);
+ _owners[3] = address(this);
+ _balances[address(this)] = 2;
+ }
+
+ function balanceOf(address owner) public view virtual returns (uint256) {
+ return _balances[owner];
+ }
+
+ function ownerOf(uint256 tokenId) public view virtual returns (address) {
+ address owner = _owners[tokenId];
+ return owner;
+ }
+
+ mapping(uint256 => address) private _owners;
+ mapping(address => uint256) private _balances;
+}
+
+interface USDCLike {
+ function isBlacklisted(address) external view returns (bool);
+}
+
+interface USDTLike {
+ function isBlackListed(address) external view returns (bool);
+}
+
+contract RevertingContract {
+ constructor() {
+ revert();
+ }
+}
+
+contract MockContractWithConstructorArgs {
+ uint256 public immutable x;
+ bool public y;
+ bytes20 public z;
+
+ constructor(uint256 _x, bool _y, bytes20 _z) payable {
+ x = _x;
+ y = _y;
+ z = _z;
+ }
+}
+
+contract MockContractPayable {
+ receive() external payable {}
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdError.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdError.t.sol
new file mode 100644
index 000000000..29803d5d5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdError.t.sol
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.0 <0.9.0;
+
+import {stdError} from "../src/StdError.sol";
+import {Test} from "../src/Test.sol";
+
+contract StdErrorsTest is Test {
+ ErrorsTest test;
+
+ function setUp() public {
+ test = new ErrorsTest();
+ }
+
+ function test_RevertIf_AssertionError() public {
+ vm.expectRevert(stdError.assertionError);
+ test.assertionError();
+ }
+
+ function test_RevertIf_ArithmeticError() public {
+ vm.expectRevert(stdError.arithmeticError);
+ test.arithmeticError(10);
+ }
+
+ function test_RevertIf_DivisionError() public {
+ vm.expectRevert(stdError.divisionError);
+ test.divError(0);
+ }
+
+ function test_RevertIf_ModError() public {
+ vm.expectRevert(stdError.divisionError);
+ test.modError(0);
+ }
+
+ function test_RevertIf_EnumConversionError() public {
+ vm.expectRevert(stdError.enumConversionError);
+ test.enumConversion(1);
+ }
+
+ function test_RevertIf_EncodeStgError() public {
+ vm.expectRevert(stdError.encodeStorageError);
+ test.encodeStgError();
+ }
+
+ function test_RevertIf_PopError() public {
+ vm.expectRevert(stdError.popError);
+ test.pop();
+ }
+
+ function test_RevertIf_IndexOOBError() public {
+ vm.expectRevert(stdError.indexOOBError);
+ test.indexOOBError(1);
+ }
+
+ function test_RevertIf_MemOverflowError() public {
+ vm.expectRevert(stdError.memOverflowError);
+ test.mem();
+ }
+
+ function test_RevertIf_InternError() public {
+ vm.expectRevert(stdError.zeroVarError);
+ test.intern();
+ }
+}
+
+contract ErrorsTest {
+ enum T {
+ T1
+ }
+
+ uint256[] public someArr;
+ bytes someBytes;
+
+ function assertionError() public pure {
+ assert(false);
+ }
+
+ function arithmeticError(uint256 a) public pure {
+ a -= 100;
+ }
+
+ function divError(uint256 a) public pure {
+ 100 / a;
+ }
+
+ function modError(uint256 a) public pure {
+ 100 % a;
+ }
+
+ function enumConversion(uint256 a) public pure {
+ T(a);
+ }
+
+ function encodeStgError() public {
+ /// @solidity memory-safe-assembly
+ assembly {
+ sstore(someBytes.slot, 1)
+ }
+ keccak256(someBytes);
+ }
+
+ function pop() public {
+ someArr.pop();
+ }
+
+ function indexOOBError(uint256 a) public pure {
+ uint256[] memory t = new uint256[](0);
+ t[a];
+ }
+
+ function mem() public pure {
+ uint256 l = 2 ** 256 / 32;
+ new uint256[](l);
+ }
+
+ function intern() public returns (uint256) {
+ function(uint256) internal returns (uint256) x;
+ x(2);
+ return 7;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdJson.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdJson.t.sol
new file mode 100644
index 000000000..6bedfcc9a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdJson.t.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, stdJson} from "../src/Test.sol";
+
+contract StdJsonTest is Test {
+ using stdJson for string;
+
+ string root;
+ string path;
+
+ function setUp() public {
+ root = vm.projectRoot();
+ path = string.concat(root, "/test/fixtures/test.json");
+ }
+
+ struct SimpleJson {
+ uint256 a;
+ string b;
+ }
+
+ struct NestedJson {
+ uint256 a;
+ string b;
+ SimpleJson c;
+ }
+
+ function test_readJson() public view {
+ string memory json = vm.readFile(path);
+ assertEq(json.readUint(".a"), 123);
+ }
+
+ function test_writeJson() public {
+ string memory json = "json";
+ json.serialize("a", uint256(123));
+ string memory semiFinal = json.serialize("b", string("test"));
+ string memory finalJson = json.serialize("c", semiFinal);
+ finalJson.write(path);
+
+ string memory json_ = vm.readFile(path);
+ bytes memory data = json_.parseRaw("$");
+ NestedJson memory decodedData = abi.decode(data, (NestedJson));
+
+ assertEq(decodedData.a, 123);
+ assertEq(decodedData.b, "test");
+ assertEq(decodedData.c.a, 123);
+ assertEq(decodedData.c.b, "test");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdMath.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdMath.t.sol
new file mode 100644
index 000000000..d1269a02a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdMath.t.sol
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.0 <0.9.0;
+
+import {stdMath} from "../src/StdMath.sol";
+import {Test, stdError} from "../src/Test.sol";
+
+contract StdMathMock is Test {
+ function exposed_percentDelta(uint256 a, uint256 b) public pure returns (uint256) {
+ return stdMath.percentDelta(a, b);
+ }
+
+ function exposed_percentDelta(int256 a, int256 b) public pure returns (uint256) {
+ return stdMath.percentDelta(a, b);
+ }
+}
+
+contract StdMathTest is Test {
+ function test_GetAbs() external pure {
+ assertEq(stdMath.abs(-50), 50);
+ assertEq(stdMath.abs(50), 50);
+ assertEq(stdMath.abs(-1337), 1337);
+ assertEq(stdMath.abs(0), 0);
+
+ assertEq(stdMath.abs(type(int256).min), (type(uint256).max >> 1) + 1);
+ assertEq(stdMath.abs(type(int256).max), (type(uint256).max >> 1));
+ }
+
+ function testFuzz_GetAbs(int256 a) external pure {
+ uint256 manualAbs = getAbs(a);
+
+ uint256 abs = stdMath.abs(a);
+
+ assertEq(abs, manualAbs);
+ }
+
+ function test_GetDelta_Uint() external pure {
+ assertEq(stdMath.delta(uint256(0), uint256(0)), 0);
+ assertEq(stdMath.delta(uint256(0), uint256(1337)), 1337);
+ assertEq(stdMath.delta(uint256(0), type(uint64).max), type(uint64).max);
+ assertEq(stdMath.delta(uint256(0), type(uint128).max), type(uint128).max);
+ assertEq(stdMath.delta(uint256(0), type(uint256).max), type(uint256).max);
+
+ assertEq(stdMath.delta(0, uint256(0)), 0);
+ assertEq(stdMath.delta(1337, uint256(0)), 1337);
+ assertEq(stdMath.delta(type(uint64).max, uint256(0)), type(uint64).max);
+ assertEq(stdMath.delta(type(uint128).max, uint256(0)), type(uint128).max);
+ assertEq(stdMath.delta(type(uint256).max, uint256(0)), type(uint256).max);
+
+ assertEq(stdMath.delta(1337, uint256(1337)), 0);
+ assertEq(stdMath.delta(type(uint256).max, type(uint256).max), 0);
+ assertEq(stdMath.delta(5000, uint256(1250)), 3750);
+ }
+
+ function testFuzz_GetDelta_Uint(uint256 a, uint256 b) external pure {
+ uint256 manualDelta = a > b ? a - b : b - a;
+
+ uint256 delta = stdMath.delta(a, b);
+
+ assertEq(delta, manualDelta);
+ }
+
+ function test_GetDelta_Int() external pure {
+ assertEq(stdMath.delta(int256(0), int256(0)), 0);
+ assertEq(stdMath.delta(int256(0), int256(1337)), 1337);
+ assertEq(stdMath.delta(int256(0), type(int64).max), type(uint64).max >> 1);
+ assertEq(stdMath.delta(int256(0), type(int128).max), type(uint128).max >> 1);
+ assertEq(stdMath.delta(int256(0), type(int256).max), type(uint256).max >> 1);
+
+ assertEq(stdMath.delta(0, int256(0)), 0);
+ assertEq(stdMath.delta(1337, int256(0)), 1337);
+ assertEq(stdMath.delta(type(int64).max, int256(0)), type(uint64).max >> 1);
+ assertEq(stdMath.delta(type(int128).max, int256(0)), type(uint128).max >> 1);
+ assertEq(stdMath.delta(type(int256).max, int256(0)), type(uint256).max >> 1);
+
+ assertEq(stdMath.delta(-0, int256(0)), 0);
+ assertEq(stdMath.delta(-1337, int256(0)), 1337);
+ assertEq(stdMath.delta(type(int64).min, int256(0)), (type(uint64).max >> 1) + 1);
+ assertEq(stdMath.delta(type(int128).min, int256(0)), (type(uint128).max >> 1) + 1);
+ assertEq(stdMath.delta(type(int256).min, int256(0)), (type(uint256).max >> 1) + 1);
+
+ assertEq(stdMath.delta(int256(0), -0), 0);
+ assertEq(stdMath.delta(int256(0), -1337), 1337);
+ assertEq(stdMath.delta(int256(0), type(int64).min), (type(uint64).max >> 1) + 1);
+ assertEq(stdMath.delta(int256(0), type(int128).min), (type(uint128).max >> 1) + 1);
+ assertEq(stdMath.delta(int256(0), type(int256).min), (type(uint256).max >> 1) + 1);
+
+ assertEq(stdMath.delta(1337, int256(1337)), 0);
+ assertEq(stdMath.delta(type(int256).max, type(int256).max), 0);
+ assertEq(stdMath.delta(type(int256).min, type(int256).min), 0);
+ assertEq(stdMath.delta(type(int256).min, type(int256).max), type(uint256).max);
+ assertEq(stdMath.delta(5000, int256(1250)), 3750);
+ }
+
+ function testFuzz_GetDelta_Int(int256 a, int256 b) external pure {
+ uint256 absA = getAbs(a);
+ uint256 absB = getAbs(b);
+ uint256 absDelta = absA > absB ? absA - absB : absB - absA;
+
+ uint256 manualDelta;
+ if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
+ manualDelta = absDelta;
+ }
+ // (a < 0 && b >= 0) || (a >= 0 && b < 0)
+ else {
+ manualDelta = absA + absB;
+ }
+
+ uint256 delta = stdMath.delta(a, b);
+
+ assertEq(delta, manualDelta);
+ }
+
+ function test_GetPercentDelta_Uint() external {
+ StdMathMock stdMathMock = new StdMathMock();
+
+ assertEq(stdMath.percentDelta(uint256(0), uint256(1337)), 1e18);
+ assertEq(stdMath.percentDelta(uint256(0), type(uint64).max), 1e18);
+ assertEq(stdMath.percentDelta(uint256(0), type(uint128).max), 1e18);
+ assertEq(stdMath.percentDelta(uint256(0), type(uint192).max), 1e18);
+
+ assertEq(stdMath.percentDelta(1337, uint256(1337)), 0);
+ assertEq(stdMath.percentDelta(type(uint192).max, type(uint192).max), 0);
+ assertEq(stdMath.percentDelta(0, uint256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(2500, uint256(2500)), 0);
+ assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18);
+
+ vm.expectRevert(stdError.divisionError);
+ stdMathMock.exposed_percentDelta(uint256(1), 0);
+ }
+
+ function testFuzz_GetPercentDelta_Uint(uint192 a, uint192 b) external pure {
+ vm.assume(b != 0);
+ uint256 manualDelta = a > b ? a - b : b - a;
+
+ uint256 manualPercentDelta = manualDelta * 1e18 / b;
+ uint256 percentDelta = stdMath.percentDelta(a, b);
+
+ assertEq(percentDelta, manualPercentDelta);
+ }
+
+ function test_GetPercentDelta_Int() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdMathMock stdMathMock = new StdMathMock();
+
+ assertEq(stdMath.percentDelta(int256(0), int256(1337)), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), -1337), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int64).min), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int128).min), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int192).min), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int64).max), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int128).max), 1e18);
+ assertEq(stdMath.percentDelta(int256(0), type(int192).max), 1e18);
+
+ assertEq(stdMath.percentDelta(1337, int256(1337)), 0);
+ assertEq(stdMath.percentDelta(type(int192).max, type(int192).max), 0);
+ assertEq(stdMath.percentDelta(type(int192).min, type(int192).min), 0);
+
+ assertEq(stdMath.percentDelta(type(int192).min, type(int192).max), 2e18); // rounds the 1 wei diff down
+ assertEq(stdMath.percentDelta(type(int192).max, type(int192).min), 2e18 - 1); // rounds the 1 wei diff down
+ assertEq(stdMath.percentDelta(0, int256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(2500, int256(2500)), 0);
+ assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18);
+ assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18);
+
+ vm.expectRevert(stdError.divisionError);
+ stdMathMock.exposed_percentDelta(int256(1), 0);
+ }
+
+ function testFuzz_GetPercentDelta_Int(int192 a, int192 b) external pure {
+ vm.assume(b != 0);
+ uint256 absA = getAbs(a);
+ uint256 absB = getAbs(b);
+ uint256 absDelta = absA > absB ? absA - absB : absB - absA;
+
+ uint256 manualDelta;
+ if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) {
+ manualDelta = absDelta;
+ }
+ // (a < 0 && b >= 0) || (a >= 0 && b < 0)
+ else {
+ manualDelta = absA + absB;
+ }
+
+ uint256 manualPercentDelta = manualDelta * 1e18 / absB;
+ uint256 percentDelta = stdMath.percentDelta(a, b);
+
+ assertEq(percentDelta, manualPercentDelta);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ HELPERS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function getAbs(int256 a) private pure returns (uint256) {
+ if (a < 0) {
+ return a == type(int256).min ? uint256(type(int256).max) + 1 : uint256(-a);
+ }
+
+ return uint256(a);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdStorage.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdStorage.t.sol
new file mode 100644
index 000000000..fd79abaae
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdStorage.t.sol
@@ -0,0 +1,471 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {stdStorage, StdStorage} from "../src/StdStorage.sol";
+import {Test} from "../src/Test.sol";
+
+contract StdStorageTest is Test {
+ using stdStorage for StdStorage;
+
+ StorageTest internal test;
+
+ function setUp() public {
+ test = new StorageTest();
+ }
+
+ function test_StorageHidden() public {
+ assertEq(uint256(keccak256("my.random.var")), stdstore.target(address(test)).sig("hidden()").find());
+ }
+
+ function test_StorageObvious() public {
+ assertEq(uint256(0), stdstore.target(address(test)).sig("exists()").find());
+ }
+
+ function test_StorageExtraSload() public {
+ assertEq(16, stdstore.target(address(test)).sig(test.extra_sload.selector).find());
+ }
+
+ function test_StorageCheckedWriteHidden() public {
+ stdstore.target(address(test)).sig(test.hidden.selector).checked_write(100);
+ assertEq(uint256(test.hidden()), 100);
+ }
+
+ function test_StorageCheckedWriteObvious() public {
+ stdstore.target(address(test)).sig(test.exists.selector).checked_write(100);
+ assertEq(test.exists(), 100);
+ }
+
+ function test_StorageCheckedWriteSignedIntegerHidden() public {
+ stdstore.target(address(test)).sig(test.hidden.selector).checked_write_int(-100);
+ assertEq(int256(uint256(test.hidden())), -100);
+ }
+
+ function test_StorageCheckedWriteSignedIntegerObvious() public {
+ stdstore.target(address(test)).sig(test.tG.selector).checked_write_int(-100);
+ assertEq(test.tG(), -100);
+ }
+
+ function test_StorageMapStructA() public {
+ uint256 slot =
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), 4))), slot);
+ }
+
+ function test_StorageMapStructB() public {
+ uint256 slot =
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), 4))) + 1, slot);
+ }
+
+ function test_StorageDeepMap() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(
+ address(this)
+ ).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(5)))))), slot);
+ }
+
+ function test_StorageCheckedWriteDeepMap() public {
+ stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(address(this))
+ .checked_write(100);
+ assertEq(100, test.deep_map(address(this), address(this)));
+ }
+
+ function test_StorageDeepMapStructA() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
+ .with_key(address(this)).depth(0).find();
+ assertEq(
+ bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0),
+ bytes32(slot)
+ );
+ }
+
+ function test_StorageDeepMapStructB() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this))
+ .with_key(address(this)).depth(1).find();
+ assertEq(
+ bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1),
+ bytes32(slot)
+ );
+ }
+
+ function test_StorageCheckedWriteDeepMapStructA() public {
+ stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key(
+ address(this)
+ ).depth(0).checked_write(100);
+ (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
+ assertEq(100, a);
+ assertEq(0, b);
+ }
+
+ function test_StorageCheckedWriteDeepMapStructB() public {
+ stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key(
+ address(this)
+ ).depth(1).checked_write(100);
+ (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this));
+ assertEq(0, a);
+ assertEq(100, b);
+ }
+
+ function test_StorageCheckedWriteMapStructA() public {
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).checked_write(100);
+ (uint256 a, uint256 b) = test.map_struct(address(this));
+ assertEq(a, 100);
+ assertEq(b, 0);
+ }
+
+ function test_StorageCheckedWriteMapStructB() public {
+ stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).checked_write(100);
+ (uint256 a, uint256 b) = test.map_struct(address(this));
+ assertEq(a, 0);
+ assertEq(b, 100);
+ }
+
+ function test_StorageStructA() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(0).find();
+ assertEq(uint256(7), slot);
+ }
+
+ function test_StorageStructB() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(1).find();
+ assertEq(uint256(7) + 1, slot);
+ }
+
+ function test_StorageCheckedWriteStructA() public {
+ stdstore.target(address(test)).sig(test.basic.selector).depth(0).checked_write(100);
+ (uint256 a, uint256 b) = test.basic();
+ assertEq(a, 100);
+ assertEq(b, 1337);
+ }
+
+ function test_StorageCheckedWriteStructB() public {
+ stdstore.target(address(test)).sig(test.basic.selector).depth(1).checked_write(100);
+ (uint256 a, uint256 b) = test.basic();
+ assertEq(a, 1337);
+ assertEq(b, 100);
+ }
+
+ function test_StorageMapAddrFound() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).find();
+ assertEq(uint256(keccak256(abi.encode(address(this), uint256(1)))), slot);
+ }
+
+ function test_StorageMapAddrRoot() public {
+ (uint256 slot, bytes32 key) =
+ stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).parent();
+ assertEq(address(uint160(uint256(key))), address(this));
+ assertEq(uint256(1), slot);
+ slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).root();
+ assertEq(uint256(1), slot);
+ }
+
+ function test_StorageMapUintFound() public {
+ uint256 slot = stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).find();
+ assertEq(uint256(keccak256(abi.encode(100, uint256(2)))), slot);
+ }
+
+ function test_StorageCheckedWriteMapUint() public {
+ stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).checked_write(100);
+ assertEq(100, test.map_uint(100));
+ }
+
+ function test_StorageCheckedWriteMapAddr() public {
+ stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).checked_write(100);
+ assertEq(100, test.map_addr(address(this)));
+ }
+
+ function test_StorageCheckedWriteMapBool() public {
+ stdstore.target(address(test)).sig(test.map_bool.selector).with_key(address(this)).checked_write(true);
+ assertTrue(test.map_bool(address(this)));
+ }
+
+ function testFuzz_StorageCheckedWriteMapPacked(address addr, uint128 value) public {
+ stdstore.enable_packed_slots().target(address(test)).sig(test.read_struct_lower.selector).with_key(addr)
+ .checked_write(value);
+ assertEq(test.read_struct_lower(addr), value);
+
+ stdstore.enable_packed_slots().target(address(test)).sig(test.read_struct_upper.selector).with_key(addr)
+ .checked_write(value);
+ assertEq(test.read_struct_upper(addr), value);
+ }
+
+ function test_StorageCheckedWriteMapPackedFullSuccess() public {
+ uint256 full = test.map_packed(address(1337));
+ // keep upper 128, set lower 128 to 1337
+ full = (full & (uint256((1 << 128) - 1) << 128)) | 1337;
+ stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337))).checked_write(
+ full
+ );
+ assertEq(1337, test.read_struct_lower(address(1337)));
+ }
+
+ function testFail_StorageConst() public {
+ // vm.expectRevert(abi.encodeWithSignature("NotStorage(bytes4)", bytes4(keccak256("const()"))));
+ stdstore.target(address(test)).sig("const()").find();
+ }
+
+ function testFuzz_StorageNativePack(uint248 val1, uint248 val2, bool boolVal1, bool boolVal2) public {
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tA.selector).checked_write(val1);
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tB.selector).checked_write(boolVal1);
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tC.selector).checked_write(boolVal2);
+ stdstore.enable_packed_slots().target(address(test)).sig(test.tD.selector).checked_write(val2);
+
+ assertEq(test.tA(), val1);
+ assertEq(test.tB(), boolVal1);
+ assertEq(test.tC(), boolVal2);
+ assertEq(test.tD(), val2);
+ }
+
+ function test_StorageReadBytes32() public {
+ bytes32 val = stdstore.target(address(test)).sig(test.tE.selector).read_bytes32();
+ assertEq(val, hex"1337");
+ }
+
+ function test_StorageReadBool_False() public {
+ bool val = stdstore.target(address(test)).sig(test.tB.selector).read_bool();
+ assertEq(val, false);
+ }
+
+ function test_StorageReadBool_True() public {
+ bool val = stdstore.target(address(test)).sig(test.tH.selector).read_bool();
+ assertEq(val, true);
+ }
+
+ function test_RevertIf_ReadingNonBoolValue() public {
+ vm.expectRevert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
+ this.readNonBoolValue();
+ }
+
+ function readNonBoolValue() public {
+ stdstore.target(address(test)).sig(test.tE.selector).read_bool();
+ }
+
+ function test_StorageReadAddress() public {
+ address val = stdstore.target(address(test)).sig(test.tF.selector).read_address();
+ assertEq(val, address(1337));
+ }
+
+ function test_StorageReadUint() public {
+ uint256 val = stdstore.target(address(test)).sig(test.exists.selector).read_uint();
+ assertEq(val, 1);
+ }
+
+ function test_StorageReadInt() public {
+ int256 val = stdstore.target(address(test)).sig(test.tG.selector).read_int();
+ assertEq(val, type(int256).min);
+ }
+
+ function testFuzz_Packed(uint256 val, uint8 elemToGet) public {
+ // This function tries an assortment of packed slots, shifts meaning number of elements
+ // that are packed. Shiftsizes are the size of each element, i.e. 8 means a data type that is 8 bits, 16 == 16 bits, etc.
+ // Combined, these determine how a slot is packed. Making it random is too hard to avoid global rejection limit
+ // and make it performant.
+
+ // change the number of shifts
+ for (uint256 i = 1; i < 5; i++) {
+ uint256 shifts = i;
+
+ elemToGet = uint8(bound(elemToGet, 0, shifts - 1));
+
+ uint256[] memory shiftSizes = new uint256[](shifts);
+ for (uint256 j; j < shifts; j++) {
+ shiftSizes[j] = 8 * (j + 1);
+ }
+
+ test.setRandomPacking(val);
+
+ uint256 leftBits;
+ uint256 rightBits;
+ for (uint256 j; j < shiftSizes.length; j++) {
+ if (j < elemToGet) {
+ leftBits += shiftSizes[j];
+ } else if (elemToGet != j) {
+ rightBits += shiftSizes[j];
+ }
+ }
+
+ // we may have some right bits unaccounted for
+ leftBits += 256 - (leftBits + shiftSizes[elemToGet] + rightBits);
+ // clear left bits, then clear right bits and realign
+ uint256 expectedValToRead = (val << leftBits) >> (leftBits + rightBits);
+
+ uint256 readVal = stdstore.target(address(test)).enable_packed_slots().sig(
+ "getRandomPacked(uint8,uint8[],uint8)"
+ ).with_calldata(abi.encode(shifts, shiftSizes, elemToGet)).read_uint();
+
+ assertEq(readVal, expectedValToRead);
+ }
+ }
+
+ function testFuzz_Packed2(uint256 nvars, uint256 seed) public {
+ // Number of random variables to generate.
+ nvars = bound(nvars, 1, 20);
+
+ // This will decrease as we generate values in the below loop.
+ uint256 bitsRemaining = 256;
+
+ // Generate a random value and size for each variable.
+ uint256[] memory vals = new uint256[](nvars);
+ uint256[] memory sizes = new uint256[](nvars);
+ uint256[] memory offsets = new uint256[](nvars);
+
+ for (uint256 i = 0; i < nvars; i++) {
+ // Generate a random value and size.
+ offsets[i] = i == 0 ? 0 : offsets[i - 1] + sizes[i - 1];
+
+ uint256 nvarsRemaining = nvars - i;
+ uint256 maxVarSize = bitsRemaining - nvarsRemaining + 1;
+ sizes[i] = bound(uint256(keccak256(abi.encodePacked(seed, i + 256))), 1, maxVarSize);
+ bitsRemaining -= sizes[i];
+
+ uint256 maxVal;
+ uint256 varSize = sizes[i];
+ assembly {
+ // mask = (1 << varSize) - 1
+ maxVal := sub(shl(varSize, 1), 1)
+ }
+ vals[i] = bound(uint256(keccak256(abi.encodePacked(seed, i))), 0, maxVal);
+ }
+
+ // Pack all values into the slot.
+ for (uint256 i = 0; i < nvars; i++) {
+ stdstore.enable_packed_slots().target(address(test)).sig("getRandomPacked(uint256,uint256)").with_key(
+ sizes[i]
+ ).with_key(offsets[i]).checked_write(vals[i]);
+ }
+
+ // Verify the read data matches.
+ for (uint256 i = 0; i < nvars; i++) {
+ uint256 readVal = stdstore.enable_packed_slots().target(address(test)).sig(
+ "getRandomPacked(uint256,uint256)"
+ ).with_key(sizes[i]).with_key(offsets[i]).read_uint();
+
+ uint256 retVal = test.getRandomPacked(sizes[i], offsets[i]);
+
+ assertEq(readVal, vals[i]);
+ assertEq(retVal, vals[i]);
+ }
+ }
+
+ function testEdgeCaseArray() public {
+ stdstore.target(address(test)).sig("edgeCaseArray(uint256)").with_key(uint256(0)).checked_write(1);
+ assertEq(test.edgeCaseArray(0), 1);
+ }
+}
+
+contract StorageTest {
+ uint256 public exists = 1;
+ mapping(address => uint256) public map_addr;
+ mapping(uint256 => uint256) public map_uint;
+ mapping(address => uint256) public map_packed;
+ mapping(address => UnpackedStruct) public map_struct;
+ mapping(address => mapping(address => uint256)) public deep_map;
+ mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
+ UnpackedStruct public basic;
+
+ uint248 public tA;
+ bool public tB;
+
+ bool public tC = false;
+ uint248 public tD = 1;
+
+ struct UnpackedStruct {
+ uint256 a;
+ uint256 b;
+ }
+
+ mapping(address => bool) public map_bool;
+
+ bytes32 public tE = hex"1337";
+ address public tF = address(1337);
+ int256 public tG = type(int256).min;
+ bool public tH = true;
+ bytes32 private tI = ~bytes32(hex"1337");
+
+ uint256 randomPacking;
+
+ // Array with length matching values of elements.
+ uint256[] public edgeCaseArray = [3, 3, 3];
+
+ constructor() {
+ basic = UnpackedStruct({a: 1337, b: 1337});
+
+ uint256 two = (1 << 128) | 1;
+ map_packed[msg.sender] = two;
+ map_packed[address(uint160(1337))] = 1 << 128;
+ }
+
+ function read_struct_upper(address who) public view returns (uint256) {
+ return map_packed[who] >> 128;
+ }
+
+ function read_struct_lower(address who) public view returns (uint256) {
+ return map_packed[who] & ((1 << 128) - 1);
+ }
+
+ function hidden() public view returns (bytes32 t) {
+ bytes32 slot = keccak256("my.random.var");
+ /// @solidity memory-safe-assembly
+ assembly {
+ t := sload(slot)
+ }
+ }
+
+ function const() public pure returns (bytes32 t) {
+ t = bytes32(hex"1337");
+ }
+
+ function extra_sload() public view returns (bytes32 t) {
+ // trigger read on slot `tE`, and make a staticcall to make sure compiler doesn't optimize this SLOAD away
+ assembly {
+ pop(staticcall(gas(), sload(tE.slot), 0, 0, 0, 0))
+ }
+ t = tI;
+ }
+
+ function setRandomPacking(uint256 val) public {
+ randomPacking = val;
+ }
+
+ function _getMask(uint256 size) internal pure returns (uint256 mask) {
+ assembly {
+ // mask = (1 << size) - 1
+ mask := sub(shl(size, 1), 1)
+ }
+ }
+
+ function setRandomPacking(uint256 val, uint256 size, uint256 offset) public {
+ // Generate mask based on the size of the value
+ uint256 mask = _getMask(size);
+ // Zero out all bits for the word we're about to set
+ uint256 cleanedWord = randomPacking & ~(mask << offset);
+ // Place val in the correct spot of the cleaned word
+ randomPacking = cleanedWord | val << offset;
+ }
+
+ function getRandomPacked(uint256 size, uint256 offset) public view returns (uint256) {
+ // Generate mask based on the size of the value
+ uint256 mask = _getMask(size);
+ // Shift to place the bits in the correct position, and use mask to zero out remaining bits
+ return (randomPacking >> offset) & mask;
+ }
+
+ function getRandomPacked(uint8 shifts, uint8[] memory shiftSizes, uint8 elem) public view returns (uint256) {
+ require(elem < shifts, "!elem");
+ uint256 leftBits;
+ uint256 rightBits;
+
+ for (uint256 i; i < shiftSizes.length; i++) {
+ if (i < elem) {
+ leftBits += shiftSizes[i];
+ } else if (elem != i) {
+ rightBits += shiftSizes[i];
+ }
+ }
+
+ // we may have some right bits unaccounted for
+ leftBits += 256 - (leftBits + shiftSizes[elem] + rightBits);
+
+ // clear left bits, then clear right bits and realign
+ return (randomPacking << leftBits) >> (leftBits + rightBits);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdStyle.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdStyle.t.sol
new file mode 100644
index 000000000..974e756fe
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdStyle.t.sol
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, console2, StdStyle} from "../src/Test.sol";
+
+contract StdStyleTest is Test {
+ function test_StyleColor() public pure {
+ console2.log(StdStyle.red("StdStyle.red String Test"));
+ console2.log(StdStyle.red(uint256(10e18)));
+ console2.log(StdStyle.red(int256(-10e18)));
+ console2.log(StdStyle.red(true));
+ console2.log(StdStyle.red(address(0)));
+ console2.log(StdStyle.redBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.redBytes32("StdStyle.redBytes32"));
+ console2.log(StdStyle.green("StdStyle.green String Test"));
+ console2.log(StdStyle.green(uint256(10e18)));
+ console2.log(StdStyle.green(int256(-10e18)));
+ console2.log(StdStyle.green(true));
+ console2.log(StdStyle.green(address(0)));
+ console2.log(StdStyle.greenBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.greenBytes32("StdStyle.greenBytes32"));
+ console2.log(StdStyle.yellow("StdStyle.yellow String Test"));
+ console2.log(StdStyle.yellow(uint256(10e18)));
+ console2.log(StdStyle.yellow(int256(-10e18)));
+ console2.log(StdStyle.yellow(true));
+ console2.log(StdStyle.yellow(address(0)));
+ console2.log(StdStyle.yellowBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.yellowBytes32("StdStyle.yellowBytes32"));
+ console2.log(StdStyle.blue("StdStyle.blue String Test"));
+ console2.log(StdStyle.blue(uint256(10e18)));
+ console2.log(StdStyle.blue(int256(-10e18)));
+ console2.log(StdStyle.blue(true));
+ console2.log(StdStyle.blue(address(0)));
+ console2.log(StdStyle.blueBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.blueBytes32("StdStyle.blueBytes32"));
+ console2.log(StdStyle.magenta("StdStyle.magenta String Test"));
+ console2.log(StdStyle.magenta(uint256(10e18)));
+ console2.log(StdStyle.magenta(int256(-10e18)));
+ console2.log(StdStyle.magenta(true));
+ console2.log(StdStyle.magenta(address(0)));
+ console2.log(StdStyle.magentaBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.magentaBytes32("StdStyle.magentaBytes32"));
+ console2.log(StdStyle.cyan("StdStyle.cyan String Test"));
+ console2.log(StdStyle.cyan(uint256(10e18)));
+ console2.log(StdStyle.cyan(int256(-10e18)));
+ console2.log(StdStyle.cyan(true));
+ console2.log(StdStyle.cyan(address(0)));
+ console2.log(StdStyle.cyanBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.cyanBytes32("StdStyle.cyanBytes32"));
+ }
+
+ function test_StyleFontWeight() public pure {
+ console2.log(StdStyle.bold("StdStyle.bold String Test"));
+ console2.log(StdStyle.bold(uint256(10e18)));
+ console2.log(StdStyle.bold(int256(-10e18)));
+ console2.log(StdStyle.bold(address(0)));
+ console2.log(StdStyle.bold(true));
+ console2.log(StdStyle.boldBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.boldBytes32("StdStyle.boldBytes32"));
+ console2.log(StdStyle.dim("StdStyle.dim String Test"));
+ console2.log(StdStyle.dim(uint256(10e18)));
+ console2.log(StdStyle.dim(int256(-10e18)));
+ console2.log(StdStyle.dim(address(0)));
+ console2.log(StdStyle.dim(true));
+ console2.log(StdStyle.dimBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.dimBytes32("StdStyle.dimBytes32"));
+ console2.log(StdStyle.italic("StdStyle.italic String Test"));
+ console2.log(StdStyle.italic(uint256(10e18)));
+ console2.log(StdStyle.italic(int256(-10e18)));
+ console2.log(StdStyle.italic(address(0)));
+ console2.log(StdStyle.italic(true));
+ console2.log(StdStyle.italicBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.italicBytes32("StdStyle.italicBytes32"));
+ console2.log(StdStyle.underline("StdStyle.underline String Test"));
+ console2.log(StdStyle.underline(uint256(10e18)));
+ console2.log(StdStyle.underline(int256(-10e18)));
+ console2.log(StdStyle.underline(address(0)));
+ console2.log(StdStyle.underline(true));
+ console2.log(StdStyle.underlineBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.underlineBytes32("StdStyle.underlineBytes32"));
+ console2.log(StdStyle.inverse("StdStyle.inverse String Test"));
+ console2.log(StdStyle.inverse(uint256(10e18)));
+ console2.log(StdStyle.inverse(int256(-10e18)));
+ console2.log(StdStyle.inverse(address(0)));
+ console2.log(StdStyle.inverse(true));
+ console2.log(StdStyle.inverseBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"));
+ console2.log(StdStyle.inverseBytes32("StdStyle.inverseBytes32"));
+ }
+
+ function test_StyleCombined() public pure {
+ console2.log(StdStyle.red(StdStyle.bold("Red Bold String Test")));
+ console2.log(StdStyle.green(StdStyle.dim(uint256(10e18))));
+ console2.log(StdStyle.yellow(StdStyle.italic(int256(-10e18))));
+ console2.log(StdStyle.blue(StdStyle.underline(address(0))));
+ console2.log(StdStyle.magenta(StdStyle.inverse(true)));
+ }
+
+ function test_StyleCustom() public pure {
+ console2.log(h1("Custom Style 1"));
+ console2.log(h2("Custom Style 2"));
+ }
+
+ function h1(string memory a) private pure returns (string memory) {
+ return StdStyle.cyan(StdStyle.inverse(StdStyle.bold(a)));
+ }
+
+ function h2(string memory a) private pure returns (string memory) {
+ return StdStyle.magenta(StdStyle.bold(StdStyle.underline(a)));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdToml.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdToml.t.sol
new file mode 100644
index 000000000..5a45f4f5c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdToml.t.sol
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, stdToml} from "../src/Test.sol";
+
+contract StdTomlTest is Test {
+ using stdToml for string;
+
+ string root;
+ string path;
+
+ function setUp() public {
+ root = vm.projectRoot();
+ path = string.concat(root, "/test/fixtures/test.toml");
+ }
+
+ struct SimpleToml {
+ uint256 a;
+ string b;
+ }
+
+ struct NestedToml {
+ uint256 a;
+ string b;
+ SimpleToml c;
+ }
+
+ function test_readToml() public view {
+ string memory json = vm.readFile(path);
+ assertEq(json.readUint(".a"), 123);
+ }
+
+ function test_writeToml() public {
+ string memory json = "json";
+ json.serialize("a", uint256(123));
+ string memory semiFinal = json.serialize("b", string("test"));
+ string memory finalJson = json.serialize("c", semiFinal);
+ finalJson.write(path);
+
+ string memory toml = vm.readFile(path);
+ bytes memory data = toml.parseRaw("$");
+ NestedToml memory decodedData = abi.decode(data, (NestedToml));
+
+ assertEq(decodedData.a, 123);
+ assertEq(decodedData.b, "test");
+ assertEq(decodedData.c.a, 123);
+ assertEq(decodedData.c.b, "test");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdUtils.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdUtils.t.sol
new file mode 100644
index 000000000..aee801b2c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/StdUtils.t.sol
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {Test, StdUtils} from "../src/Test.sol";
+
+contract StdUtilsMock is StdUtils {
+ // We deploy a mock version so we can properly test expected reverts.
+ function exposed_getTokenBalances(address token, address[] memory addresses)
+ external
+ returns (uint256[] memory balances)
+ {
+ return getTokenBalances(token, addresses);
+ }
+
+ function exposed_bound(int256 num, int256 min, int256 max) external pure returns (int256) {
+ return bound(num, min, max);
+ }
+
+ function exposed_bound(uint256 num, uint256 min, uint256 max) external pure returns (uint256) {
+ return bound(num, min, max);
+ }
+
+ function exposed_bytesToUint(bytes memory b) external pure returns (uint256) {
+ return bytesToUint(b);
+ }
+}
+
+contract StdUtilsTest is Test {
+ /*//////////////////////////////////////////////////////////////////////////
+ BOUND UINT
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_Bound() public pure {
+ assertEq(bound(uint256(5), 0, 4), 0);
+ assertEq(bound(uint256(0), 69, 69), 69);
+ assertEq(bound(uint256(0), 68, 69), 68);
+ assertEq(bound(uint256(10), 150, 190), 174);
+ assertEq(bound(uint256(300), 2800, 3200), 3107);
+ assertEq(bound(uint256(9999), 1337, 6666), 4669);
+ }
+
+ function test_Bound_WithinRange() public pure {
+ assertEq(bound(uint256(51), 50, 150), 51);
+ assertEq(bound(uint256(51), 50, 150), bound(bound(uint256(51), 50, 150), 50, 150));
+ assertEq(bound(uint256(149), 50, 150), 149);
+ assertEq(bound(uint256(149), 50, 150), bound(bound(uint256(149), 50, 150), 50, 150));
+ }
+
+ function test_Bound_EdgeCoverage() public pure {
+ assertEq(bound(uint256(0), 50, 150), 50);
+ assertEq(bound(uint256(1), 50, 150), 51);
+ assertEq(bound(uint256(2), 50, 150), 52);
+ assertEq(bound(uint256(3), 50, 150), 53);
+ assertEq(bound(type(uint256).max, 50, 150), 150);
+ assertEq(bound(type(uint256).max - 1, 50, 150), 149);
+ assertEq(bound(type(uint256).max - 2, 50, 150), 148);
+ assertEq(bound(type(uint256).max - 3, 50, 150), 147);
+ }
+
+ function testFuzz_Bound_DistributionIsEven(uint256 min, uint256 size) public pure {
+ size = size % 100 + 1;
+ min = bound(min, UINT256_MAX / 2, UINT256_MAX / 2 + size);
+ uint256 max = min + size - 1;
+ uint256 result;
+
+ for (uint256 i = 1; i <= size * 4; ++i) {
+ // x > max
+ result = bound(max + i, min, max);
+ assertEq(result, min + (i - 1) % size);
+ // x < min
+ result = bound(min - i, min, max);
+ assertEq(result, max - (i - 1) % size);
+ }
+ }
+
+ function testFuzz_Bound(uint256 num, uint256 min, uint256 max) public pure {
+ if (min > max) (min, max) = (max, min);
+
+ uint256 result = bound(num, min, max);
+
+ assertGe(result, min);
+ assertLe(result, max);
+ assertEq(result, bound(result, min, max));
+ if (num >= min && num <= max) assertEq(result, num);
+ }
+
+ function test_BoundUint256Max() public pure {
+ assertEq(bound(0, type(uint256).max - 1, type(uint256).max), type(uint256).max - 1);
+ assertEq(bound(1, type(uint256).max - 1, type(uint256).max), type(uint256).max);
+ }
+
+ function test_RevertIf_BoundMaxLessThanMin() public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
+ stdUtils.exposed_bound(uint256(5), 100, 10);
+ }
+
+ function testFuzz_RevertIf_BoundMaxLessThanMin(uint256 num, uint256 min, uint256 max) public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.assume(min > max);
+ vm.expectRevert(bytes("StdUtils bound(uint256,uint256,uint256): Max is less than min."));
+ stdUtils.exposed_bound(num, min, max);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ BOUND INT
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_BoundInt() public pure {
+ assertEq(bound(-3, 0, 4), 2);
+ assertEq(bound(0, -69, -69), -69);
+ assertEq(bound(0, -69, -68), -68);
+ assertEq(bound(-10, 150, 190), 154);
+ assertEq(bound(-300, 2800, 3200), 2908);
+ assertEq(bound(9999, -1337, 6666), 1995);
+ }
+
+ function test_BoundInt_WithinRange() public pure {
+ assertEq(bound(51, -50, 150), 51);
+ assertEq(bound(51, -50, 150), bound(bound(51, -50, 150), -50, 150));
+ assertEq(bound(149, -50, 150), 149);
+ assertEq(bound(149, -50, 150), bound(bound(149, -50, 150), -50, 150));
+ }
+
+ function test_BoundInt_EdgeCoverage() public pure {
+ assertEq(bound(type(int256).min, -50, 150), -50);
+ assertEq(bound(type(int256).min + 1, -50, 150), -49);
+ assertEq(bound(type(int256).min + 2, -50, 150), -48);
+ assertEq(bound(type(int256).min + 3, -50, 150), -47);
+ assertEq(bound(type(int256).min, 10, 150), 10);
+ assertEq(bound(type(int256).min + 1, 10, 150), 11);
+ assertEq(bound(type(int256).min + 2, 10, 150), 12);
+ assertEq(bound(type(int256).min + 3, 10, 150), 13);
+
+ assertEq(bound(type(int256).max, -50, 150), 150);
+ assertEq(bound(type(int256).max - 1, -50, 150), 149);
+ assertEq(bound(type(int256).max - 2, -50, 150), 148);
+ assertEq(bound(type(int256).max - 3, -50, 150), 147);
+ assertEq(bound(type(int256).max, -50, -10), -10);
+ assertEq(bound(type(int256).max - 1, -50, -10), -11);
+ assertEq(bound(type(int256).max - 2, -50, -10), -12);
+ assertEq(bound(type(int256).max - 3, -50, -10), -13);
+ }
+
+ function testFuzz_BoundInt_DistributionIsEven(int256 min, uint256 size) public pure {
+ size = size % 100 + 1;
+ min = bound(min, -int256(size / 2), int256(size - size / 2));
+ int256 max = min + int256(size) - 1;
+ int256 result;
+
+ for (uint256 i = 1; i <= size * 4; ++i) {
+ // x > max
+ result = bound(max + int256(i), min, max);
+ assertEq(result, min + int256((i - 1) % size));
+ // x < min
+ result = bound(min - int256(i), min, max);
+ assertEq(result, max - int256((i - 1) % size));
+ }
+ }
+
+ function testFuzz_BoundInt(int256 num, int256 min, int256 max) public pure {
+ if (min > max) (min, max) = (max, min);
+
+ int256 result = bound(num, min, max);
+
+ assertGe(result, min);
+ assertLe(result, max);
+ assertEq(result, bound(result, min, max));
+ if (num >= min && num <= max) assertEq(result, num);
+ }
+
+ function test_BoundIntInt256Max() public pure {
+ assertEq(bound(0, type(int256).max - 1, type(int256).max), type(int256).max - 1);
+ assertEq(bound(1, type(int256).max - 1, type(int256).max), type(int256).max);
+ }
+
+ function test_BoundIntInt256Min() public pure {
+ assertEq(bound(0, type(int256).min, type(int256).min + 1), type(int256).min);
+ assertEq(bound(1, type(int256).min, type(int256).min + 1), type(int256).min + 1);
+ }
+
+ function test_RevertIf_BoundIntMaxLessThanMin() public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
+ stdUtils.exposed_bound(-5, 100, 10);
+ }
+
+ function testFuzz_RevertIf_BoundIntMaxLessThanMin(int256 num, int256 min, int256 max) public {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ vm.assume(min > max);
+ vm.expectRevert(bytes("StdUtils bound(int256,int256,int256): Max is less than min."));
+ stdUtils.exposed_bound(num, min, max);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ BOUND PRIVATE KEY
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_BoundPrivateKey() public pure {
+ assertEq(boundPrivateKey(0), 1);
+ assertEq(boundPrivateKey(1), 1);
+ assertEq(boundPrivateKey(300), 300);
+ assertEq(boundPrivateKey(9999), 9999);
+ assertEq(boundPrivateKey(SECP256K1_ORDER - 1), SECP256K1_ORDER - 1);
+ assertEq(boundPrivateKey(SECP256K1_ORDER), 1);
+ assertEq(boundPrivateKey(SECP256K1_ORDER + 1), 2);
+ assertEq(boundPrivateKey(UINT256_MAX), UINT256_MAX & SECP256K1_ORDER - 1); // x&y is equivalent to x-x%y
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ BYTES TO UINT
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_BytesToUint() external pure {
+ bytes memory maxUint = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ bytes memory two = hex"02";
+ bytes memory millionEther = hex"d3c21bcecceda1000000";
+
+ assertEq(bytesToUint(maxUint), type(uint256).max);
+ assertEq(bytesToUint(two), 2);
+ assertEq(bytesToUint(millionEther), 1_000_000 ether);
+ }
+
+ function test_RevertIf_BytesLengthExceeds32() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ bytes memory thirty3Bytes = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ vm.expectRevert("StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
+ stdUtils.exposed_bytesToUint(thirty3Bytes);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ COMPUTE CREATE ADDRESS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_ComputeCreateAddress() external pure {
+ address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
+ uint256 nonce = 14;
+ address createAddress = computeCreateAddress(deployer, nonce);
+ assertEq(createAddress, 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ COMPUTE CREATE2 ADDRESS
+ //////////////////////////////////////////////////////////////////////////*/
+
+ function test_ComputeCreate2Address() external pure {
+ bytes32 salt = bytes32(uint256(31415));
+ bytes32 initcodeHash = keccak256(abi.encode(0x6080));
+ address deployer = 0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9;
+ address create2Address = computeCreate2Address(salt, initcodeHash, deployer);
+ assertEq(create2Address, 0xB147a5d25748fda14b463EB04B111027C290f4d3);
+ }
+
+ function test_ComputeCreate2AddressWithDefaultDeployer() external pure {
+ bytes32 salt = 0xc290c670fde54e5ef686f9132cbc8711e76a98f0333a438a92daa442c71403c0;
+ bytes32 initcodeHash = hashInitCode(hex"6080", "");
+ assertEq(initcodeHash, 0x1a578b7a4b0b5755db6d121b4118d4bc68fe170dca840c59bc922f14175a76b0);
+ address create2Address = computeCreate2Address(salt, initcodeHash);
+ assertEq(create2Address, 0xc0ffEe2198a06235aAbFffe5Db0CacF1717f5Ac6);
+ }
+}
+
+contract StdUtilsForkTest is Test {
+ /*//////////////////////////////////////////////////////////////////////////
+ GET TOKEN BALANCES
+ //////////////////////////////////////////////////////////////////////////*/
+
+ address internal SHIB = 0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE;
+ address internal SHIB_HOLDER_0 = 0x855F5981e831D83e6A4b4EBFCAdAa68D92333170;
+ address internal SHIB_HOLDER_1 = 0x8F509A90c2e47779cA408Fe00d7A72e359229AdA;
+ address internal SHIB_HOLDER_2 = 0x0e3bbc0D04fF62211F71f3e4C45d82ad76224385;
+
+ address internal USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
+ address internal USDC_HOLDER_0 = 0xDa9CE944a37d218c3302F6B82a094844C6ECEb17;
+ address internal USDC_HOLDER_1 = 0x3e67F4721E6d1c41a015f645eFa37BEd854fcf52;
+
+ function setUp() public {
+ // All tests of the `getTokenBalances` method are fork tests using live contracts.
+ vm.createSelectFork({urlOrAlias: "mainnet", blockNumber: 16_428_900});
+ }
+
+ function test_RevertIf_CannotGetTokenBalances_NonTokenContract() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ // The UniswapV2Factory contract has neither a `balanceOf` function nor a fallback function,
+ // so the `balanceOf` call should revert.
+ address token = address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);
+ address[] memory addresses = new address[](1);
+ addresses[0] = USDC_HOLDER_0;
+
+ vm.expectRevert("Multicall3: call failed");
+ stdUtils.exposed_getTokenBalances(token, addresses);
+ }
+
+ function test_RevertIf_CannotGetTokenBalances_EOA() external {
+ // We deploy a mock version so we can properly test the revert.
+ StdUtilsMock stdUtils = new StdUtilsMock();
+
+ address eoa = vm.addr({privateKey: 1});
+ address[] memory addresses = new address[](1);
+ addresses[0] = USDC_HOLDER_0;
+ vm.expectRevert("StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
+ stdUtils.exposed_getTokenBalances(eoa, addresses);
+ }
+
+ function test_GetTokenBalances_Empty() external {
+ address[] memory addresses = new address[](0);
+ uint256[] memory balances = getTokenBalances(USDC, addresses);
+ assertEq(balances.length, 0);
+ }
+
+ function test_GetTokenBalances_USDC() external {
+ address[] memory addresses = new address[](2);
+ addresses[0] = USDC_HOLDER_0;
+ addresses[1] = USDC_HOLDER_1;
+ uint256[] memory balances = getTokenBalances(USDC, addresses);
+ assertEq(balances[0], 159_000_000_000_000);
+ assertEq(balances[1], 131_350_000_000_000);
+ }
+
+ function test_GetTokenBalances_SHIB() external {
+ address[] memory addresses = new address[](3);
+ addresses[0] = SHIB_HOLDER_0;
+ addresses[1] = SHIB_HOLDER_1;
+ addresses[2] = SHIB_HOLDER_2;
+ uint256[] memory balances = getTokenBalances(SHIB, addresses);
+ assertEq(balances[0], 3_323_256_285_484.42e18);
+ assertEq(balances[1], 1_271_702_771_149.99999928e18);
+ assertEq(balances[2], 606_357_106_247e18);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/Vm.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/Vm.t.sol
new file mode 100644
index 000000000..7135409db
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/Vm.t.sol
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.8.0 <0.9.0;
+
+import {Test} from "../src/Test.sol";
+import {Vm, VmSafe} from "../src/Vm.sol";
+
+// These tests ensure that functions are never accidentally removed from a Vm interface, or
+// inadvertently moved between Vm and VmSafe. These tests must be updated each time a function is
+// added to or removed from Vm or VmSafe.
+contract VmTest is Test {
+ function test_VmInterfaceId() public pure {
+ assertEq(type(Vm).interfaceId, bytes4(0xa561dbe8), "Vm");
+ }
+
+ function test_VmSafeInterfaceId() public pure {
+ assertEq(type(VmSafe).interfaceId, bytes4(0x681d10d4), "VmSafe");
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationScript.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationScript.sol
new file mode 100644
index 000000000..e205cfff3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationScript.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import "../../src/Script.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationScript is Script {}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationScriptBase.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationScriptBase.sol
new file mode 100644
index 000000000..ce8e0e954
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationScriptBase.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import "../../src/Script.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationScriptBase is ScriptBase {}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationTest.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationTest.sol
new file mode 100644
index 000000000..9beeafeb7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationTest.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import "../../src/Test.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationTest is Test {}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationTestBase.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationTestBase.sol
new file mode 100644
index 000000000..e993535bc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/compilation/CompilationTestBase.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.6.2 <0.9.0;
+
+pragma experimental ABIEncoderV2;
+
+import "../../src/Test.sol";
+
+// The purpose of this contract is to benchmark compilation time to avoid accidentally introducing
+// a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207
+contract CompilationTestBase is TestBase {}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/broadcast.log.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/broadcast.log.json
new file mode 100644
index 000000000..0a0200bca
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/broadcast.log.json
@@ -0,0 +1,187 @@
+{
+ "transactions": [
+ {
+ "hash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f",
+ "type": "CALL",
+ "contractName": "Test",
+ "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "function": "multiple_arguments(uint256,address,uint256[]):(uint256)",
+ "arguments": ["1", "0000000000000000000000000000000000001337", "[3,4]"],
+ "tx": {
+ "type": "0x02",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "gas": "0x73b9",
+ "value": "0x0",
+ "data": "0x23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004",
+ "nonce": "0x3",
+ "accessList": []
+ }
+ },
+ {
+ "hash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298",
+ "type": "CALL",
+ "contractName": "Test",
+ "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "function": "inc():(uint256)",
+ "arguments": [],
+ "tx": {
+ "type": "0x02",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "gas": "0xdcb2",
+ "value": "0x0",
+ "data": "0x371303c0",
+ "nonce": "0x4",
+ "accessList": []
+ }
+ },
+ {
+ "hash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
+ "type": "CALL",
+ "contractName": "Test",
+ "contractAddress": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "function": "t(uint256):(uint256)",
+ "arguments": ["1"],
+ "tx": {
+ "type": "0x02",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "gas": "0x8599",
+ "value": "0x0",
+ "data": "0xafe29f710000000000000000000000000000000000000000000000000000000000000001",
+ "nonce": "0x5",
+ "accessList": []
+ }
+ }
+ ],
+ "receipts": [
+ {
+ "transactionHash": "0x481dc86e40bba90403c76f8e144aa9ff04c1da2164299d0298573835f0991181",
+ "transactionIndex": "0x0",
+ "blockHash": "0xef0730448490304e5403be0fa8f8ce64f118e9adcca60c07a2ae1ab921d748af",
+ "blockNumber": "0x1",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": null,
+ "cumulativeGasUsed": "0x13f3a",
+ "gasUsed": "0x13f3a",
+ "contractAddress": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0x6a187183545b8a9e7f1790e847139379bf5622baff2cb43acf3f5c79470af782",
+ "transactionIndex": "0x0",
+ "blockHash": "0xf3acb96a90071640c2a8c067ae4e16aad87e634ea8d8bbbb5b352fba86ba0148",
+ "blockNumber": "0x2",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": null,
+ "cumulativeGasUsed": "0x45d80",
+ "gasUsed": "0x45d80",
+ "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0x064ad173b4867bdef2fb60060bbdaf01735fbf10414541ea857772974e74ea9d",
+ "transactionIndex": "0x0",
+ "blockHash": "0x8373d02109d3ee06a0225f23da4c161c656ccc48fe0fcee931d325508ae73e58",
+ "blockNumber": "0x3",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c",
+ "cumulativeGasUsed": "0x45feb",
+ "gasUsed": "0x45feb",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f",
+ "transactionIndex": "0x0",
+ "blockHash": "0x16712fae5c0e18f75045f84363fb6b4d9a9fe25e660c4ce286833a533c97f629",
+ "blockNumber": "0x4",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "cumulativeGasUsed": "0x5905",
+ "gasUsed": "0x5905",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298",
+ "transactionIndex": "0x0",
+ "blockHash": "0x156b88c3eb9a1244ba00a1834f3f70de735b39e3e59006dd03af4fe7d5480c11",
+ "blockNumber": "0x5",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512",
+ "cumulativeGasUsed": "0xa9c4",
+ "gasUsed": "0xa9c4",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
+ "transactionIndex": "0x0",
+ "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb",
+ "blockNumber": "0x6",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "cumulativeGasUsed": "0x66c5",
+ "gasUsed": "0x66c5",
+ "contractAddress": null,
+ "logs": [
+ {
+ "address": "0x7c6b4bbe207d642d98d5c537142d85209e585087",
+ "topics": [
+ "0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b"
+ ],
+ "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000046865726500000000000000000000000000000000000000000000000000000000",
+ "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb",
+ "blockNumber": "0x6",
+ "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c",
+ "transactionIndex": "0x1",
+ "logIndex": "0x0",
+ "transactionLogIndex": "0x0",
+ "removed": false
+ }
+ ],
+ "status": "0x1",
+ "logsBloom": "0x00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100",
+ "effectiveGasPrice": "0xee6b2800"
+ },
+ {
+ "transactionHash": "0x11fbb10230c168ca1e36a7e5c69a6dbcd04fd9e64ede39d10a83e36ee8065c16",
+ "transactionIndex": "0x0",
+ "blockHash": "0xf1e0ed2eda4e923626ec74621006ed50b3fc27580dc7b4cf68a07ca77420e29c",
+ "blockNumber": "0x7",
+ "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
+ "to": "0x0000000000000000000000000000000000001337",
+ "cumulativeGasUsed": "0x5208",
+ "gasUsed": "0x5208",
+ "contractAddress": null,
+ "logs": [],
+ "status": "0x1",
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "effectiveGasPrice": "0xee6b2800"
+ }
+ ],
+ "libraries": [
+ "src/Broadcast.t.sol:F:0x5fbdb2315678afecb367f032d93f642f64180aa3"
+ ],
+ "pending": [],
+ "path": "broadcast/Broadcast.t.sol/31337/run-latest.json",
+ "returns": {},
+ "timestamp": 1655140035
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/test.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/test.json
new file mode 100644
index 000000000..caebf6d96
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/test.json
@@ -0,0 +1,8 @@
+{
+ "a": 123,
+ "b": "test",
+ "c": {
+ "a": 123,
+ "b": "test"
+ }
+}
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/test.toml b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/test.toml
new file mode 100644
index 000000000..60692bc75
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/fixtures/test.toml
@@ -0,0 +1,6 @@
+a = 123
+b = "test"
+
+[c]
+a = 123
+b = "test"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/mocks/MockERC20.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/mocks/MockERC20.t.sol
new file mode 100644
index 000000000..e24681093
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/mocks/MockERC20.t.sol
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {MockERC20} from "../../src/mocks/MockERC20.sol";
+import {StdCheats} from "../../src/StdCheats.sol";
+import {Test} from "../../src/Test.sol";
+
+contract Token_ERC20 is MockERC20 {
+ constructor(string memory name, string memory symbol, uint8 decimals) {
+ initialize(name, symbol, decimals);
+ }
+
+ function mint(address to, uint256 value) public virtual {
+ _mint(to, value);
+ }
+
+ function burn(address from, uint256 value) public virtual {
+ _burn(from, value);
+ }
+}
+
+contract MockERC20Test is StdCheats, Test {
+ Token_ERC20 token;
+
+ bytes32 constant PERMIT_TYPEHASH =
+ keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
+
+ function setUp() public {
+ token = new Token_ERC20("Token", "TKN", 18);
+ }
+
+ function invariantMetadata() public view {
+ assertEq(token.name(), "Token");
+ assertEq(token.symbol(), "TKN");
+ assertEq(token.decimals(), 18);
+ }
+
+ function testMint() public {
+ token.mint(address(0xBEEF), 1e18);
+
+ assertEq(token.totalSupply(), 1e18);
+ assertEq(token.balanceOf(address(0xBEEF)), 1e18);
+ }
+
+ function testBurn() public {
+ token.mint(address(0xBEEF), 1e18);
+ token.burn(address(0xBEEF), 0.9e18);
+
+ assertEq(token.totalSupply(), 1e18 - 0.9e18);
+ assertEq(token.balanceOf(address(0xBEEF)), 0.1e18);
+ }
+
+ function testApprove() public {
+ assertTrue(token.approve(address(0xBEEF), 1e18));
+
+ assertEq(token.allowance(address(this), address(0xBEEF)), 1e18);
+ }
+
+ function testTransfer() public {
+ token.mint(address(this), 1e18);
+
+ assertTrue(token.transfer(address(0xBEEF), 1e18));
+ assertEq(token.totalSupply(), 1e18);
+
+ assertEq(token.balanceOf(address(this)), 0);
+ assertEq(token.balanceOf(address(0xBEEF)), 1e18);
+ }
+
+ function testTransferFrom() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 1e18);
+
+ vm.prank(from);
+ token.approve(address(this), 1e18);
+
+ assertTrue(token.transferFrom(from, address(0xBEEF), 1e18));
+ assertEq(token.totalSupply(), 1e18);
+
+ assertEq(token.allowance(from, address(this)), 0);
+
+ assertEq(token.balanceOf(from), 0);
+ assertEq(token.balanceOf(address(0xBEEF)), 1e18);
+ }
+
+ function testInfiniteApproveTransferFrom() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 1e18);
+
+ vm.prank(from);
+ token.approve(address(this), type(uint256).max);
+
+ assertTrue(token.transferFrom(from, address(0xBEEF), 1e18));
+ assertEq(token.totalSupply(), 1e18);
+
+ assertEq(token.allowance(from, address(this)), type(uint256).max);
+
+ assertEq(token.balanceOf(from), 0);
+ assertEq(token.balanceOf(address(0xBEEF)), 1e18);
+ }
+
+ function testPermit() public {
+ uint256 privateKey = 0xBEEF;
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, address(0xCAFE), 1e18, 0, block.timestamp))
+ )
+ )
+ );
+
+ token.permit(owner, address(0xCAFE), 1e18, block.timestamp, v, r, s);
+
+ assertEq(token.allowance(owner, address(0xCAFE)), 1e18);
+ assertEq(token.nonces(owner), 1);
+ }
+
+ function testFailTransferInsufficientBalance() public {
+ token.mint(address(this), 0.9e18);
+ token.transfer(address(0xBEEF), 1e18);
+ }
+
+ function testFailTransferFromInsufficientAllowance() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 1e18);
+
+ vm.prank(from);
+ token.approve(address(this), 0.9e18);
+
+ token.transferFrom(from, address(0xBEEF), 1e18);
+ }
+
+ function testFailTransferFromInsufficientBalance() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 0.9e18);
+
+ vm.prank(from);
+ token.approve(address(this), 1e18);
+
+ token.transferFrom(from, address(0xBEEF), 1e18);
+ }
+
+ function testFailPermitBadNonce() public {
+ uint256 privateKey = 0xBEEF;
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, address(0xCAFE), 1e18, 1, block.timestamp))
+ )
+ )
+ );
+
+ token.permit(owner, address(0xCAFE), 1e18, block.timestamp, v, r, s);
+ }
+
+ function testFailPermitBadDeadline() public {
+ uint256 privateKey = 0xBEEF;
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, address(0xCAFE), 1e18, 0, block.timestamp))
+ )
+ )
+ );
+
+ token.permit(owner, address(0xCAFE), 1e18, block.timestamp + 1, v, r, s);
+ }
+
+ function testFailPermitPastDeadline() public {
+ uint256 oldTimestamp = block.timestamp;
+ uint256 privateKey = 0xBEEF;
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, address(0xCAFE), 1e18, 0, oldTimestamp))
+ )
+ )
+ );
+
+ vm.warp(block.timestamp + 1);
+ token.permit(owner, address(0xCAFE), 1e18, oldTimestamp, v, r, s);
+ }
+
+ function testFailPermitReplay() public {
+ uint256 privateKey = 0xBEEF;
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, address(0xCAFE), 1e18, 0, block.timestamp))
+ )
+ )
+ );
+
+ token.permit(owner, address(0xCAFE), 1e18, block.timestamp, v, r, s);
+ token.permit(owner, address(0xCAFE), 1e18, block.timestamp, v, r, s);
+ }
+
+ function testMetadata(string calldata name, string calldata symbol, uint8 decimals) public {
+ Token_ERC20 tkn = new Token_ERC20(name, symbol, decimals);
+ assertEq(tkn.name(), name);
+ assertEq(tkn.symbol(), symbol);
+ assertEq(tkn.decimals(), decimals);
+ }
+
+ function testMint(address from, uint256 amount) public {
+ token.mint(from, amount);
+
+ assertEq(token.totalSupply(), amount);
+ assertEq(token.balanceOf(from), amount);
+ }
+
+ function testBurn(address from, uint256 mintAmount, uint256 burnAmount) public {
+ burnAmount = bound(burnAmount, 0, mintAmount);
+
+ token.mint(from, mintAmount);
+ token.burn(from, burnAmount);
+
+ assertEq(token.totalSupply(), mintAmount - burnAmount);
+ assertEq(token.balanceOf(from), mintAmount - burnAmount);
+ }
+
+ function testApprove(address to, uint256 amount) public {
+ assertTrue(token.approve(to, amount));
+
+ assertEq(token.allowance(address(this), to), amount);
+ }
+
+ function testTransfer(address from, uint256 amount) public {
+ token.mint(address(this), amount);
+
+ assertTrue(token.transfer(from, amount));
+ assertEq(token.totalSupply(), amount);
+
+ if (address(this) == from) {
+ assertEq(token.balanceOf(address(this)), amount);
+ } else {
+ assertEq(token.balanceOf(address(this)), 0);
+ assertEq(token.balanceOf(from), amount);
+ }
+ }
+
+ function testTransferFrom(address to, uint256 approval, uint256 amount) public {
+ amount = bound(amount, 0, approval);
+
+ address from = address(0xABCD);
+
+ token.mint(from, amount);
+
+ vm.prank(from);
+ token.approve(address(this), approval);
+
+ assertTrue(token.transferFrom(from, to, amount));
+ assertEq(token.totalSupply(), amount);
+
+ uint256 app = from == address(this) || approval == type(uint256).max ? approval : approval - amount;
+ assertEq(token.allowance(from, address(this)), app);
+
+ if (from == to) {
+ assertEq(token.balanceOf(from), amount);
+ } else {
+ assertEq(token.balanceOf(from), 0);
+ assertEq(token.balanceOf(to), amount);
+ }
+ }
+
+ function testPermit(uint248 privKey, address to, uint256 amount, uint256 deadline) public {
+ uint256 privateKey = privKey;
+ if (deadline < block.timestamp) deadline = block.timestamp;
+ if (privateKey == 0) privateKey = 1;
+
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, to, amount, 0, deadline))
+ )
+ )
+ );
+
+ token.permit(owner, to, amount, deadline, v, r, s);
+
+ assertEq(token.allowance(owner, to), amount);
+ assertEq(token.nonces(owner), 1);
+ }
+
+ function testFailBurnInsufficientBalance(address to, uint256 mintAmount, uint256 burnAmount) public {
+ burnAmount = bound(burnAmount, mintAmount + 1, type(uint256).max);
+
+ token.mint(to, mintAmount);
+ token.burn(to, burnAmount);
+ }
+
+ function testFailTransferInsufficientBalance(address to, uint256 mintAmount, uint256 sendAmount) public {
+ sendAmount = bound(sendAmount, mintAmount + 1, type(uint256).max);
+
+ token.mint(address(this), mintAmount);
+ token.transfer(to, sendAmount);
+ }
+
+ function testFailTransferFromInsufficientAllowance(address to, uint256 approval, uint256 amount) public {
+ amount = bound(amount, approval + 1, type(uint256).max);
+
+ address from = address(0xABCD);
+
+ token.mint(from, amount);
+
+ vm.prank(from);
+ token.approve(address(this), approval);
+
+ token.transferFrom(from, to, amount);
+ }
+
+ function testFailTransferFromInsufficientBalance(address to, uint256 mintAmount, uint256 sendAmount) public {
+ sendAmount = bound(sendAmount, mintAmount + 1, type(uint256).max);
+
+ address from = address(0xABCD);
+
+ token.mint(from, mintAmount);
+
+ vm.prank(from);
+ token.approve(address(this), sendAmount);
+
+ token.transferFrom(from, to, sendAmount);
+ }
+
+ function testFailPermitBadNonce(uint256 privateKey, address to, uint256 amount, uint256 deadline, uint256 nonce)
+ public
+ {
+ if (deadline < block.timestamp) deadline = block.timestamp;
+ if (privateKey == 0) privateKey = 1;
+ if (nonce == 0) nonce = 1;
+
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, to, amount, nonce, deadline))
+ )
+ )
+ );
+
+ token.permit(owner, to, amount, deadline, v, r, s);
+ }
+
+ function testFailPermitBadDeadline(uint256 privateKey, address to, uint256 amount, uint256 deadline) public {
+ if (deadline < block.timestamp) deadline = block.timestamp;
+ if (privateKey == 0) privateKey = 1;
+
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, to, amount, 0, deadline))
+ )
+ )
+ );
+
+ token.permit(owner, to, amount, deadline + 1, v, r, s);
+ }
+
+ function testFailPermitPastDeadline(uint256 privateKey, address to, uint256 amount, uint256 deadline) public {
+ deadline = bound(deadline, 0, block.timestamp - 1);
+ if (privateKey == 0) privateKey = 1;
+
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, to, amount, 0, deadline))
+ )
+ )
+ );
+
+ token.permit(owner, to, amount, deadline, v, r, s);
+ }
+
+ function testFailPermitReplay(uint256 privateKey, address to, uint256 amount, uint256 deadline) public {
+ if (deadline < block.timestamp) deadline = block.timestamp;
+ if (privateKey == 0) privateKey = 1;
+
+ address owner = vm.addr(privateKey);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ privateKey,
+ keccak256(
+ abi.encodePacked(
+ "\x19\x01",
+ token.DOMAIN_SEPARATOR(),
+ keccak256(abi.encode(PERMIT_TYPEHASH, owner, to, amount, 0, deadline))
+ )
+ )
+ );
+
+ token.permit(owner, to, amount, deadline, v, r, s);
+ token.permit(owner, to, amount, deadline, v, r, s);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/mocks/MockERC721.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/mocks/MockERC721.t.sol
new file mode 100644
index 000000000..f986d7967
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/forge-std/test/mocks/MockERC721.t.sol
@@ -0,0 +1,721 @@
+// SPDX-License-Identifier: MIT
+pragma solidity >=0.7.0 <0.9.0;
+
+import {MockERC721, IERC721TokenReceiver} from "../../src/mocks/MockERC721.sol";
+import {StdCheats} from "../../src/StdCheats.sol";
+import {Test} from "../../src/Test.sol";
+
+contract ERC721Recipient is IERC721TokenReceiver {
+ address public operator;
+ address public from;
+ uint256 public id;
+ bytes public data;
+
+ function onERC721Received(address _operator, address _from, uint256 _id, bytes calldata _data)
+ public
+ virtual
+ override
+ returns (bytes4)
+ {
+ operator = _operator;
+ from = _from;
+ id = _id;
+ data = _data;
+
+ return IERC721TokenReceiver.onERC721Received.selector;
+ }
+}
+
+contract RevertingERC721Recipient is IERC721TokenReceiver {
+ function onERC721Received(address, address, uint256, bytes calldata) public virtual override returns (bytes4) {
+ revert(string(abi.encodePacked(IERC721TokenReceiver.onERC721Received.selector)));
+ }
+}
+
+contract WrongReturnDataERC721Recipient is IERC721TokenReceiver {
+ function onERC721Received(address, address, uint256, bytes calldata) public virtual override returns (bytes4) {
+ return 0xCAFEBEEF;
+ }
+}
+
+contract NonERC721Recipient {}
+
+contract Token_ERC721 is MockERC721 {
+ constructor(string memory _name, string memory _symbol) {
+ initialize(_name, _symbol);
+ }
+
+ function tokenURI(uint256) public pure virtual override returns (string memory) {}
+
+ function mint(address to, uint256 tokenId) public virtual {
+ _mint(to, tokenId);
+ }
+
+ function burn(uint256 tokenId) public virtual {
+ _burn(tokenId);
+ }
+
+ function safeMint(address to, uint256 tokenId) public virtual {
+ _safeMint(to, tokenId);
+ }
+
+ function safeMint(address to, uint256 tokenId, bytes memory data) public virtual {
+ _safeMint(to, tokenId, data);
+ }
+}
+
+contract MockERC721Test is StdCheats, Test {
+ Token_ERC721 token;
+
+ function setUp() public {
+ token = new Token_ERC721("Token", "TKN");
+ }
+
+ function invariantMetadata() public view {
+ assertEq(token.name(), "Token");
+ assertEq(token.symbol(), "TKN");
+ }
+
+ function testMint() public {
+ token.mint(address(0xBEEF), 1337);
+
+ assertEq(token.balanceOf(address(0xBEEF)), 1);
+ assertEq(token.ownerOf(1337), address(0xBEEF));
+ }
+
+ function testBurn() public {
+ token.mint(address(0xBEEF), 1337);
+ token.burn(1337);
+
+ assertEq(token.balanceOf(address(0xBEEF)), 0);
+
+ vm.expectRevert("NOT_MINTED");
+ token.ownerOf(1337);
+ }
+
+ function testApprove() public {
+ token.mint(address(this), 1337);
+
+ token.approve(address(0xBEEF), 1337);
+
+ assertEq(token.getApproved(1337), address(0xBEEF));
+ }
+
+ function testApproveBurn() public {
+ token.mint(address(this), 1337);
+
+ token.approve(address(0xBEEF), 1337);
+
+ token.burn(1337);
+
+ assertEq(token.balanceOf(address(this)), 0);
+ assertEq(token.getApproved(1337), address(0));
+
+ vm.expectRevert("NOT_MINTED");
+ token.ownerOf(1337);
+ }
+
+ function testApproveAll() public {
+ token.setApprovalForAll(address(0xBEEF), true);
+
+ assertTrue(token.isApprovedForAll(address(this), address(0xBEEF)));
+ }
+
+ function testTransferFrom() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 1337);
+
+ vm.prank(from);
+ token.approve(address(this), 1337);
+
+ token.transferFrom(from, address(0xBEEF), 1337);
+
+ assertEq(token.getApproved(1337), address(0));
+ assertEq(token.ownerOf(1337), address(0xBEEF));
+ assertEq(token.balanceOf(address(0xBEEF)), 1);
+ assertEq(token.balanceOf(from), 0);
+ }
+
+ function testTransferFromSelf() public {
+ token.mint(address(this), 1337);
+
+ token.transferFrom(address(this), address(0xBEEF), 1337);
+
+ assertEq(token.getApproved(1337), address(0));
+ assertEq(token.ownerOf(1337), address(0xBEEF));
+ assertEq(token.balanceOf(address(0xBEEF)), 1);
+ assertEq(token.balanceOf(address(this)), 0);
+ }
+
+ function testTransferFromApproveAll() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 1337);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.transferFrom(from, address(0xBEEF), 1337);
+
+ assertEq(token.getApproved(1337), address(0));
+ assertEq(token.ownerOf(1337), address(0xBEEF));
+ assertEq(token.balanceOf(address(0xBEEF)), 1);
+ assertEq(token.balanceOf(from), 0);
+ }
+
+ function testSafeTransferFromToEOA() public {
+ address from = address(0xABCD);
+
+ token.mint(from, 1337);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.safeTransferFrom(from, address(0xBEEF), 1337);
+
+ assertEq(token.getApproved(1337), address(0));
+ assertEq(token.ownerOf(1337), address(0xBEEF));
+ assertEq(token.balanceOf(address(0xBEEF)), 1);
+ assertEq(token.balanceOf(from), 0);
+ }
+
+ function testSafeTransferFromToERC721Recipient() public {
+ address from = address(0xABCD);
+ ERC721Recipient recipient = new ERC721Recipient();
+
+ token.mint(from, 1337);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.safeTransferFrom(from, address(recipient), 1337);
+
+ assertEq(token.getApproved(1337), address(0));
+ assertEq(token.ownerOf(1337), address(recipient));
+ assertEq(token.balanceOf(address(recipient)), 1);
+ assertEq(token.balanceOf(from), 0);
+
+ assertEq(recipient.operator(), address(this));
+ assertEq(recipient.from(), from);
+ assertEq(recipient.id(), 1337);
+ assertEq(recipient.data(), "");
+ }
+
+ function testSafeTransferFromToERC721RecipientWithData() public {
+ address from = address(0xABCD);
+ ERC721Recipient recipient = new ERC721Recipient();
+
+ token.mint(from, 1337);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.safeTransferFrom(from, address(recipient), 1337, "testing 123");
+
+ assertEq(token.getApproved(1337), address(0));
+ assertEq(token.ownerOf(1337), address(recipient));
+ assertEq(token.balanceOf(address(recipient)), 1);
+ assertEq(token.balanceOf(from), 0);
+
+ assertEq(recipient.operator(), address(this));
+ assertEq(recipient.from(), from);
+ assertEq(recipient.id(), 1337);
+ assertEq(recipient.data(), "testing 123");
+ }
+
+ function testSafeMintToEOA() public {
+ token.safeMint(address(0xBEEF), 1337);
+
+ assertEq(token.ownerOf(1337), address(address(0xBEEF)));
+ assertEq(token.balanceOf(address(address(0xBEEF))), 1);
+ }
+
+ function testSafeMintToERC721Recipient() public {
+ ERC721Recipient to = new ERC721Recipient();
+
+ token.safeMint(address(to), 1337);
+
+ assertEq(token.ownerOf(1337), address(to));
+ assertEq(token.balanceOf(address(to)), 1);
+
+ assertEq(to.operator(), address(this));
+ assertEq(to.from(), address(0));
+ assertEq(to.id(), 1337);
+ assertEq(to.data(), "");
+ }
+
+ function testSafeMintToERC721RecipientWithData() public {
+ ERC721Recipient to = new ERC721Recipient();
+
+ token.safeMint(address(to), 1337, "testing 123");
+
+ assertEq(token.ownerOf(1337), address(to));
+ assertEq(token.balanceOf(address(to)), 1);
+
+ assertEq(to.operator(), address(this));
+ assertEq(to.from(), address(0));
+ assertEq(to.id(), 1337);
+ assertEq(to.data(), "testing 123");
+ }
+
+ function testFailMintToZero() public {
+ token.mint(address(0), 1337);
+ }
+
+ function testFailDoubleMint() public {
+ token.mint(address(0xBEEF), 1337);
+ token.mint(address(0xBEEF), 1337);
+ }
+
+ function testFailBurnUnMinted() public {
+ token.burn(1337);
+ }
+
+ function testFailDoubleBurn() public {
+ token.mint(address(0xBEEF), 1337);
+
+ token.burn(1337);
+ token.burn(1337);
+ }
+
+ function testFailApproveUnMinted() public {
+ token.approve(address(0xBEEF), 1337);
+ }
+
+ function testFailApproveUnAuthorized() public {
+ token.mint(address(0xCAFE), 1337);
+
+ token.approve(address(0xBEEF), 1337);
+ }
+
+ function testFailTransferFromUnOwned() public {
+ token.transferFrom(address(0xFEED), address(0xBEEF), 1337);
+ }
+
+ function testFailTransferFromWrongFrom() public {
+ token.mint(address(0xCAFE), 1337);
+
+ token.transferFrom(address(0xFEED), address(0xBEEF), 1337);
+ }
+
+ function testFailTransferFromToZero() public {
+ token.mint(address(this), 1337);
+
+ token.transferFrom(address(this), address(0), 1337);
+ }
+
+ function testFailTransferFromNotOwner() public {
+ token.mint(address(0xFEED), 1337);
+
+ token.transferFrom(address(0xFEED), address(0xBEEF), 1337);
+ }
+
+ function testFailSafeTransferFromToNonERC721Recipient() public {
+ token.mint(address(this), 1337);
+
+ token.safeTransferFrom(address(this), address(new NonERC721Recipient()), 1337);
+ }
+
+ function testFailSafeTransferFromToNonERC721RecipientWithData() public {
+ token.mint(address(this), 1337);
+
+ token.safeTransferFrom(address(this), address(new NonERC721Recipient()), 1337, "testing 123");
+ }
+
+ function testFailSafeTransferFromToRevertingERC721Recipient() public {
+ token.mint(address(this), 1337);
+
+ token.safeTransferFrom(address(this), address(new RevertingERC721Recipient()), 1337);
+ }
+
+ function testFailSafeTransferFromToRevertingERC721RecipientWithData() public {
+ token.mint(address(this), 1337);
+
+ token.safeTransferFrom(address(this), address(new RevertingERC721Recipient()), 1337, "testing 123");
+ }
+
+ function testFailSafeTransferFromToERC721RecipientWithWrongReturnData() public {
+ token.mint(address(this), 1337);
+
+ token.safeTransferFrom(address(this), address(new WrongReturnDataERC721Recipient()), 1337);
+ }
+
+ function testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData() public {
+ token.mint(address(this), 1337);
+
+ token.safeTransferFrom(address(this), address(new WrongReturnDataERC721Recipient()), 1337, "testing 123");
+ }
+
+ function testFailSafeMintToNonERC721Recipient() public {
+ token.safeMint(address(new NonERC721Recipient()), 1337);
+ }
+
+ function testFailSafeMintToNonERC721RecipientWithData() public {
+ token.safeMint(address(new NonERC721Recipient()), 1337, "testing 123");
+ }
+
+ function testFailSafeMintToRevertingERC721Recipient() public {
+ token.safeMint(address(new RevertingERC721Recipient()), 1337);
+ }
+
+ function testFailSafeMintToRevertingERC721RecipientWithData() public {
+ token.safeMint(address(new RevertingERC721Recipient()), 1337, "testing 123");
+ }
+
+ function testFailSafeMintToERC721RecipientWithWrongReturnData() public {
+ token.safeMint(address(new WrongReturnDataERC721Recipient()), 1337);
+ }
+
+ function testFailSafeMintToERC721RecipientWithWrongReturnDataWithData() public {
+ token.safeMint(address(new WrongReturnDataERC721Recipient()), 1337, "testing 123");
+ }
+
+ function testFailBalanceOfZeroAddress() public view {
+ token.balanceOf(address(0));
+ }
+
+ function testFailOwnerOfUnminted() public view {
+ token.ownerOf(1337);
+ }
+
+ function testMetadata(string memory name, string memory symbol) public {
+ MockERC721 tkn = new Token_ERC721(name, symbol);
+
+ assertEq(tkn.name(), name);
+ assertEq(tkn.symbol(), symbol);
+ }
+
+ function testMint(address to, uint256 id) public {
+ if (to == address(0)) to = address(0xBEEF);
+
+ token.mint(to, id);
+
+ assertEq(token.balanceOf(to), 1);
+ assertEq(token.ownerOf(id), to);
+ }
+
+ function testBurn(address to, uint256 id) public {
+ if (to == address(0)) to = address(0xBEEF);
+
+ token.mint(to, id);
+ token.burn(id);
+
+ assertEq(token.balanceOf(to), 0);
+
+ vm.expectRevert("NOT_MINTED");
+ token.ownerOf(id);
+ }
+
+ function testApprove(address to, uint256 id) public {
+ if (to == address(0)) to = address(0xBEEF);
+
+ token.mint(address(this), id);
+
+ token.approve(to, id);
+
+ assertEq(token.getApproved(id), to);
+ }
+
+ function testApproveBurn(address to, uint256 id) public {
+ token.mint(address(this), id);
+
+ token.approve(address(to), id);
+
+ token.burn(id);
+
+ assertEq(token.balanceOf(address(this)), 0);
+ assertEq(token.getApproved(id), address(0));
+
+ vm.expectRevert("NOT_MINTED");
+ token.ownerOf(id);
+ }
+
+ function testApproveAll(address to, bool approved) public {
+ token.setApprovalForAll(to, approved);
+
+ assertEq(token.isApprovedForAll(address(this), to), approved);
+ }
+
+ function testTransferFrom(uint256 id, address to) public {
+ address from = address(0xABCD);
+
+ if (to == address(0) || to == from) to = address(0xBEEF);
+
+ token.mint(from, id);
+
+ vm.prank(from);
+ token.approve(address(this), id);
+
+ token.transferFrom(from, to, id);
+
+ assertEq(token.getApproved(id), address(0));
+ assertEq(token.ownerOf(id), to);
+ assertEq(token.balanceOf(to), 1);
+ assertEq(token.balanceOf(from), 0);
+ }
+
+ function testTransferFromSelf(uint256 id, address to) public {
+ if (to == address(0) || to == address(this)) to = address(0xBEEF);
+
+ token.mint(address(this), id);
+
+ token.transferFrom(address(this), to, id);
+
+ assertEq(token.getApproved(id), address(0));
+ assertEq(token.ownerOf(id), to);
+ assertEq(token.balanceOf(to), 1);
+ assertEq(token.balanceOf(address(this)), 0);
+ }
+
+ function testTransferFromApproveAll(uint256 id, address to) public {
+ address from = address(0xABCD);
+
+ if (to == address(0) || to == from) to = address(0xBEEF);
+
+ token.mint(from, id);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.transferFrom(from, to, id);
+
+ assertEq(token.getApproved(id), address(0));
+ assertEq(token.ownerOf(id), to);
+ assertEq(token.balanceOf(to), 1);
+ assertEq(token.balanceOf(from), 0);
+ }
+
+ function testSafeTransferFromToEOA(uint256 id, address to) public {
+ address from = address(0xABCD);
+
+ if (to == address(0) || to == from) to = address(0xBEEF);
+
+ if (uint256(uint160(to)) <= 18 || to.code.length > 0) return;
+
+ token.mint(from, id);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.safeTransferFrom(from, to, id);
+
+ assertEq(token.getApproved(id), address(0));
+ assertEq(token.ownerOf(id), to);
+ assertEq(token.balanceOf(to), 1);
+ assertEq(token.balanceOf(from), 0);
+ }
+
+ function testSafeTransferFromToERC721Recipient(uint256 id) public {
+ address from = address(0xABCD);
+
+ ERC721Recipient recipient = new ERC721Recipient();
+
+ token.mint(from, id);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.safeTransferFrom(from, address(recipient), id);
+
+ assertEq(token.getApproved(id), address(0));
+ assertEq(token.ownerOf(id), address(recipient));
+ assertEq(token.balanceOf(address(recipient)), 1);
+ assertEq(token.balanceOf(from), 0);
+
+ assertEq(recipient.operator(), address(this));
+ assertEq(recipient.from(), from);
+ assertEq(recipient.id(), id);
+ assertEq(recipient.data(), "");
+ }
+
+ function testSafeTransferFromToERC721RecipientWithData(uint256 id, bytes calldata data) public {
+ address from = address(0xABCD);
+ ERC721Recipient recipient = new ERC721Recipient();
+
+ token.mint(from, id);
+
+ vm.prank(from);
+ token.setApprovalForAll(address(this), true);
+
+ token.safeTransferFrom(from, address(recipient), id, data);
+
+ assertEq(token.getApproved(id), address(0));
+ assertEq(token.ownerOf(id), address(recipient));
+ assertEq(token.balanceOf(address(recipient)), 1);
+ assertEq(token.balanceOf(from), 0);
+
+ assertEq(recipient.operator(), address(this));
+ assertEq(recipient.from(), from);
+ assertEq(recipient.id(), id);
+ assertEq(recipient.data(), data);
+ }
+
+ function testSafeMintToEOA(uint256 id, address to) public {
+ if (to == address(0)) to = address(0xBEEF);
+
+ if (uint256(uint160(to)) <= 18 || to.code.length > 0) return;
+
+ token.safeMint(to, id);
+
+ assertEq(token.ownerOf(id), address(to));
+ assertEq(token.balanceOf(address(to)), 1);
+ }
+
+ function testSafeMintToERC721Recipient(uint256 id) public {
+ ERC721Recipient to = new ERC721Recipient();
+
+ token.safeMint(address(to), id);
+
+ assertEq(token.ownerOf(id), address(to));
+ assertEq(token.balanceOf(address(to)), 1);
+
+ assertEq(to.operator(), address(this));
+ assertEq(to.from(), address(0));
+ assertEq(to.id(), id);
+ assertEq(to.data(), "");
+ }
+
+ function testSafeMintToERC721RecipientWithData(uint256 id, bytes calldata data) public {
+ ERC721Recipient to = new ERC721Recipient();
+
+ token.safeMint(address(to), id, data);
+
+ assertEq(token.ownerOf(id), address(to));
+ assertEq(token.balanceOf(address(to)), 1);
+
+ assertEq(to.operator(), address(this));
+ assertEq(to.from(), address(0));
+ assertEq(to.id(), id);
+ assertEq(to.data(), data);
+ }
+
+ function testFailMintToZero(uint256 id) public {
+ token.mint(address(0), id);
+ }
+
+ function testFailDoubleMint(uint256 id, address to) public {
+ if (to == address(0)) to = address(0xBEEF);
+
+ token.mint(to, id);
+ token.mint(to, id);
+ }
+
+ function testFailBurnUnMinted(uint256 id) public {
+ token.burn(id);
+ }
+
+ function testFailDoubleBurn(uint256 id, address to) public {
+ if (to == address(0)) to = address(0xBEEF);
+
+ token.mint(to, id);
+
+ token.burn(id);
+ token.burn(id);
+ }
+
+ function testFailApproveUnMinted(uint256 id, address to) public {
+ token.approve(to, id);
+ }
+
+ function testFailApproveUnAuthorized(address owner, uint256 id, address to) public {
+ if (owner == address(0) || owner == address(this)) owner = address(0xBEEF);
+
+ token.mint(owner, id);
+
+ token.approve(to, id);
+ }
+
+ function testFailTransferFromUnOwned(address from, address to, uint256 id) public {
+ token.transferFrom(from, to, id);
+ }
+
+ function testFailTransferFromWrongFrom(address owner, address from, address to, uint256 id) public {
+ if (owner == address(0)) to = address(0xBEEF);
+ if (from == owner) revert();
+
+ token.mint(owner, id);
+
+ token.transferFrom(from, to, id);
+ }
+
+ function testFailTransferFromToZero(uint256 id) public {
+ token.mint(address(this), id);
+
+ token.transferFrom(address(this), address(0), id);
+ }
+
+ function testFailTransferFromNotOwner(address from, address to, uint256 id) public {
+ if (from == address(this)) from = address(0xBEEF);
+
+ token.mint(from, id);
+
+ token.transferFrom(from, to, id);
+ }
+
+ function testFailSafeTransferFromToNonERC721Recipient(uint256 id) public {
+ token.mint(address(this), id);
+
+ token.safeTransferFrom(address(this), address(new NonERC721Recipient()), id);
+ }
+
+ function testFailSafeTransferFromToNonERC721RecipientWithData(uint256 id, bytes calldata data) public {
+ token.mint(address(this), id);
+
+ token.safeTransferFrom(address(this), address(new NonERC721Recipient()), id, data);
+ }
+
+ function testFailSafeTransferFromToRevertingERC721Recipient(uint256 id) public {
+ token.mint(address(this), id);
+
+ token.safeTransferFrom(address(this), address(new RevertingERC721Recipient()), id);
+ }
+
+ function testFailSafeTransferFromToRevertingERC721RecipientWithData(uint256 id, bytes calldata data) public {
+ token.mint(address(this), id);
+
+ token.safeTransferFrom(address(this), address(new RevertingERC721Recipient()), id, data);
+ }
+
+ function testFailSafeTransferFromToERC721RecipientWithWrongReturnData(uint256 id) public {
+ token.mint(address(this), id);
+
+ token.safeTransferFrom(address(this), address(new WrongReturnDataERC721Recipient()), id);
+ }
+
+ function testFailSafeTransferFromToERC721RecipientWithWrongReturnDataWithData(uint256 id, bytes calldata data)
+ public
+ {
+ token.mint(address(this), id);
+
+ token.safeTransferFrom(address(this), address(new WrongReturnDataERC721Recipient()), id, data);
+ }
+
+ function testFailSafeMintToNonERC721Recipient(uint256 id) public {
+ token.safeMint(address(new NonERC721Recipient()), id);
+ }
+
+ function testFailSafeMintToNonERC721RecipientWithData(uint256 id, bytes calldata data) public {
+ token.safeMint(address(new NonERC721Recipient()), id, data);
+ }
+
+ function testFailSafeMintToRevertingERC721Recipient(uint256 id) public {
+ token.safeMint(address(new RevertingERC721Recipient()), id);
+ }
+
+ function testFailSafeMintToRevertingERC721RecipientWithData(uint256 id, bytes calldata data) public {
+ token.safeMint(address(new RevertingERC721Recipient()), id, data);
+ }
+
+ function testFailSafeMintToERC721RecipientWithWrongReturnData(uint256 id) public {
+ token.safeMint(address(new WrongReturnDataERC721Recipient()), id);
+ }
+
+ function testFailSafeMintToERC721RecipientWithWrongReturnDataWithData(uint256 id, bytes calldata data) public {
+ token.safeMint(address(new WrongReturnDataERC721Recipient()), id, data);
+ }
+
+ function testFailOwnerOfUnminted(uint256 id) public view {
+ token.ownerOf(id);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/LICENSE b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/LICENSE
new file mode 100644
index 000000000..0ad25db4b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/LICENSE
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+ .
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/README.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/README.md
new file mode 100644
index 000000000..3b6912fc3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/README.md
@@ -0,0 +1,100 @@
+# Halmos Cheat Codes
+
+Halmos cheatcodes are abstract functions designed to facilitate writing symbolic tests, such as the creation of new symbolic values at runtime. While these cheatcodes are currently exclusive to [Halmos][halmos], they are not limited to it and could potentially be supported by other symbolic testing tools in the future.
+
+Please refer to [the list of currently available cheatcodes][list]. More cheatcodes will be added in the future.
+
+Join the [Halmos Telegram Group][chat] for any inquiries or further discussions.
+
+[halmos]: https://github.com/a16z/halmos
+[list]: src/SVM.sol
+[chat]: https://t.me/+4UhzHduai3MzZmUx
+
+## Installation
+
+To install using Foundry:
+
+```
+forge install a16z/halmos-cheatcodes
+```
+
+Alternatively, you can directly add it as a submodule:
+
+```
+git submodule add https://github.com/a16z/halmos-cheatcodes
+```
+
+## Example usage
+
+Below is an example of a symbolic test that checks for potential unauthorized access to others' tokens. The approach involves setting up an initial symbolic state of the token contract, executing an arbitrary function call to the token contract, and checking if there is an execution path that increases the caller's balance and/or decreases the balance of others. This example illustrates how to utilize cheatcodes to set up initial symbolic states and execute arbitrary function calls.
+
+```solidity
+// import Halmos cheatcodes
+import { SymTest } from 'halmos-cheatcodes/SymTest.sol';
+
+import { Test } from 'forge-std/Test.sol';
+
+import { Token } from '/path/to/Token.sol';
+
+contract TokenTest is SymTest, Test {
+ Token token;
+
+ function setUp() public {
+ token = new Token();
+
+ // set the balances of three arbitrary accounts to arbitrary symbolic values
+ for (uint256 i = 0; i < 3; i++) {
+ address receiver = svm.createAddress('receiver'); // create a new symbolic address
+ uint256 amount = svm.createUint256('amount'); // create a new symbolic uint256 value
+ token.transfer(receiver, amount);
+ }
+ }
+
+ function checkBalanceUpdate() public {
+ // consider two arbitrary distinct accounts
+ address caller = svm.createAddress('caller'); // create a symbolic address
+ address others = svm.createAddress('others'); // create another symbolic address
+ vm.assume(others != caller); // assume the two addresses are different
+
+ // record their current balances
+ uint256 oldBalanceCaller = token.balanceOf(caller);
+ uint256 oldBalanceOthers = token.balanceOf(others);
+
+ // execute an arbitrary function call to the token from the caller
+ vm.prank(caller);
+ uint256 dataSize = 100; // the max calldata size for the public functions in the token
+ bytes memory data = svm.createBytes(dataSize, 'data'); // create a symbolic calldata
+ address(token).call(data);
+
+ // ensure that the caller cannot spend others' tokens
+ assert(token.balanceOf(caller) <= oldBalanceCaller); // cannot increase their own balance
+ assert(token.balanceOf(others) >= oldBalanceOthers); // cannot decrease others' balance
+ }
+}
+```
+
+When running the above test against the following buggy token contract, Halmos will provide a counterexample that may be overlooked during manual reviews.
+
+```solidity
+/// @notice This is a buggy token contract. DO NOT use it in production.
+contract Token {
+ mapping(address => uint) public balanceOf;
+
+ constructor() public {
+ balanceOf[msg.sender] = 1e27;
+ }
+
+ function transfer(address to, uint amount) public {
+ _transfer(msg.sender, to, amount);
+ }
+
+ function _transfer(address from, address to, uint amount) public {
+ balanceOf[from] -= amount;
+ balanceOf[to] += amount;
+ }
+}
+```
+
+## Disclaimer
+
+_These smart contracts and code are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts and code. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions or loss of transmitted information. THE SMART CONTRACTS AND CODE CONTAINED HEREIN ARE FURNISHED AS IS, WHERE IS, WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, NON-INFRINGEMENT OR FITNESS FOR ANY PARTICULAR PURPOSE. Further, use of any of these smart contracts and code may be restricted or prohibited under applicable law, including securities laws, and it is therefore strongly advised for you to contact a reputable attorney in any jurisdiction where these smart contracts and code may be accessible for any questions or concerns with respect thereto. Further, no information provided in this repo should be construed as investment advice or legal advice for any particular facts or circumstances, and is not meant to replace competent counsel. a16z is not liable for any use of the foregoing, and users should proceed with caution and use at their own risk. See a16z.com/disclosures for more info._
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/SVM.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/SVM.sol
new file mode 100644
index 000000000..e9ba3ea04
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/SVM.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: AGPL-3.0
+pragma solidity >=0.8.0 <0.9.0;
+
+/// @notice Symbolic Virtual Machine
+interface SVM {
+ // Create a new symbolic uint value ranging over [0, 2**bitSize - 1] (inclusive)
+ function createUint(uint256 bitSize, string memory name) external pure returns (uint256 value);
+
+ // Create a new symbolic uint256 value
+ function createUint256(string memory name) external pure returns (uint256 value);
+
+ // Create a new symbolic signed int value
+ function createInt(uint256 bitSize, string memory name) external pure returns (int256 value);
+
+ // Create a new symbolic int256 value
+ function createInt256(string memory name) external pure returns (int256 value);
+
+ // Create a new symbolic byte array with the given byte size
+ function createBytes(uint256 byteSize, string memory name) external pure returns (bytes memory value);
+
+ // Create a new symbolic string backed by a symbolic array with the given byte size
+ function createString(uint256 byteSize, string memory name) external pure returns (string memory value);
+
+ // Create a new symbolic bytes32 value
+ function createBytes32(string memory name) external pure returns (bytes32 value);
+
+ // Create a new symbolic bytes4 value
+ function createBytes4(string memory name) external pure returns (bytes4 value);
+
+ // Create a new symbolic address value
+ function createAddress(string memory name) external pure returns (address value);
+
+ // Create a new symbolic boolean value
+ function createBool(string memory name) external pure returns (bool value);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/SymTest.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/SymTest.sol
new file mode 100644
index 000000000..96684ed87
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/SymTest.sol
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: AGPL-3.0
+pragma solidity >=0.8.0 <0.9.0;
+
+import {SVM} from "./SVM.sol";
+
+abstract contract SymTest {
+ // SVM cheat code address: 0xf3993a62377bcd56ae39d773740a5390411e8bc9
+ address internal constant SVM_ADDRESS = address(uint160(uint256(keccak256("svm cheat code"))));
+
+ SVM internal constant svm = SVM(SVM_ADDRESS);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/logo.svg b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/logo.svg
new file mode 100644
index 000000000..f1e14c2bb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/logo.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/netlify.toml b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/netlify.toml
new file mode 100644
index 000000000..0447f41ad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/netlify.toml
@@ -0,0 +1,3 @@
+[build]
+command = "npm run docs"
+publish = "build/site"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/package-lock.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/package-lock.json
new file mode 100644
index 000000000..16012fe11
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/package-lock.json
@@ -0,0 +1,11554 @@
+{
+ "name": "openzeppelin-solidity",
+ "version": "5.2.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "openzeppelin-solidity",
+ "version": "5.2.0",
+ "license": "MIT",
+ "devDependencies": {
+ "@changesets/changelog-github": "^0.5.0",
+ "@changesets/cli": "^2.26.0",
+ "@changesets/pre": "^2.0.0",
+ "@changesets/read": "^0.6.0",
+ "@eslint/compat": "^1.2.1",
+ "@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
+ "@nomicfoundation/hardhat-ethers": "^3.0.4",
+ "@nomicfoundation/hardhat-network-helpers": "^1.0.3",
+ "@openzeppelin/docs-utils": "^0.1.5",
+ "@openzeppelin/merkle-tree": "^1.0.7",
+ "@openzeppelin/upgrade-safe-transpiler": "^0.3.32",
+ "@openzeppelin/upgrades-core": "^1.20.6",
+ "chai": "^4.2.0",
+ "eslint": "^9.0.0",
+ "eslint-config-prettier": "^9.0.0",
+ "ethers": "^6.16.0",
+ "glob": "^11.1.0",
+ "globals": "^15.3.0",
+ "graphlib": "^2.1.8",
+ "hardhat": "^2.22.2",
+ "hardhat-exposed": "^0.3.15",
+ "hardhat-gas-reporter": "^2.3.0",
+ "hardhat-ignore-warnings": "^0.2.11",
+ "lodash.startcase": "^4.4.0",
+ "micromatch": "^4.0.8",
+ "p-limit": "^3.1.0",
+ "prettier": "^3.0.0",
+ "prettier-plugin-solidity": "^1.1.0",
+ "rimraf": "^6.0.0",
+ "semver": "^7.3.5",
+ "solhint": "^5.0.0",
+ "solhint-plugin-openzeppelin": "file:scripts/solhint-custom",
+ "solidity-ast": "^0.4.50",
+ "solidity-coverage": "^0.8.17",
+ "solidity-docgen": "^0.6.0-beta.29",
+ "undici": "^6.23.0",
+ "yargs": "^17.0.0"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@adraffy/ens-normalize": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz",
+ "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+ "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@changesets/apply-release-plan": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.4.tgz",
+ "integrity": "sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/config": "^2.3.1",
+ "@changesets/get-version-range-type": "^0.3.2",
+ "@changesets/git": "^2.0.0",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "detect-indent": "^6.0.0",
+ "fs-extra": "^7.0.1",
+ "lodash.startcase": "^4.4.0",
+ "outdent": "^0.5.0",
+ "prettier": "^2.7.1",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.3"
+ }
+ },
+ "node_modules/@changesets/apply-release-plan/node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/@changesets/assemble-release-plan": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.2.4.tgz",
+ "integrity": "sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/errors": "^0.1.4",
+ "@changesets/get-dependents-graph": "^1.3.6",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "semver": "^7.5.3"
+ }
+ },
+ "node_modules/@changesets/changelog-git": {
+ "version": "0.1.14",
+ "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.1.14.tgz",
+ "integrity": "sha512-+vRfnKtXVWsDDxGctOfzJsPhaCdXRYoe+KyWYoq5X/GqoISREiat0l3L8B0a453B2B4dfHGcZaGyowHbp9BSaA==",
+ "dev": true,
+ "dependencies": {
+ "@changesets/types": "^5.2.1"
+ }
+ },
+ "node_modules/@changesets/changelog-github": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@changesets/changelog-github/-/changelog-github-0.5.0.tgz",
+ "integrity": "sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==",
+ "dev": true,
+ "dependencies": {
+ "@changesets/get-github-info": "^0.6.0",
+ "@changesets/types": "^6.0.0",
+ "dotenv": "^8.1.0"
+ }
+ },
+ "node_modules/@changesets/changelog-github/node_modules/@changesets/types": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.0.0.tgz",
+ "integrity": "sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==",
+ "dev": true
+ },
+ "node_modules/@changesets/cli": {
+ "version": "2.26.2",
+ "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.26.2.tgz",
+ "integrity": "sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/apply-release-plan": "^6.1.4",
+ "@changesets/assemble-release-plan": "^5.2.4",
+ "@changesets/changelog-git": "^0.1.14",
+ "@changesets/config": "^2.3.1",
+ "@changesets/errors": "^0.1.4",
+ "@changesets/get-dependents-graph": "^1.3.6",
+ "@changesets/get-release-plan": "^3.0.17",
+ "@changesets/git": "^2.0.0",
+ "@changesets/logger": "^0.0.5",
+ "@changesets/pre": "^1.0.14",
+ "@changesets/read": "^0.5.9",
+ "@changesets/types": "^5.2.1",
+ "@changesets/write": "^0.2.3",
+ "@manypkg/get-packages": "^1.1.3",
+ "@types/is-ci": "^3.0.0",
+ "@types/semver": "^7.5.0",
+ "ansi-colors": "^4.1.3",
+ "chalk": "^2.1.0",
+ "enquirer": "^2.3.0",
+ "external-editor": "^3.1.0",
+ "fs-extra": "^7.0.1",
+ "human-id": "^1.0.2",
+ "is-ci": "^3.0.1",
+ "meow": "^6.0.0",
+ "outdent": "^0.5.0",
+ "p-limit": "^2.2.0",
+ "preferred-pm": "^3.0.0",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.3",
+ "spawndamnit": "^2.0.0",
+ "term-size": "^2.1.0",
+ "tty-table": "^4.1.5"
+ },
+ "bin": {
+ "changeset": "bin.js"
+ }
+ },
+ "node_modules/@changesets/cli/node_modules/@changesets/pre": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.14.tgz",
+ "integrity": "sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/errors": "^0.1.4",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "fs-extra": "^7.0.1"
+ }
+ },
+ "node_modules/@changesets/cli/node_modules/@changesets/read": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.5.9.tgz",
+ "integrity": "sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/git": "^2.0.0",
+ "@changesets/logger": "^0.0.5",
+ "@changesets/parse": "^0.3.16",
+ "@changesets/types": "^5.2.1",
+ "chalk": "^2.1.0",
+ "fs-extra": "^7.0.1",
+ "p-filter": "^2.1.0"
+ }
+ },
+ "node_modules/@changesets/cli/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@changesets/config": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@changesets/config/-/config-2.3.1.tgz",
+ "integrity": "sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==",
+ "dev": true,
+ "dependencies": {
+ "@changesets/errors": "^0.1.4",
+ "@changesets/get-dependents-graph": "^1.3.6",
+ "@changesets/logger": "^0.0.5",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "fs-extra": "^7.0.1",
+ "micromatch": "^4.0.2"
+ }
+ },
+ "node_modules/@changesets/errors": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.1.4.tgz",
+ "integrity": "sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==",
+ "dev": true,
+ "dependencies": {
+ "extendable-error": "^0.1.5"
+ }
+ },
+ "node_modules/@changesets/get-dependents-graph": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.6.tgz",
+ "integrity": "sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==",
+ "dev": true,
+ "dependencies": {
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "chalk": "^2.1.0",
+ "fs-extra": "^7.0.1",
+ "semver": "^7.5.3"
+ }
+ },
+ "node_modules/@changesets/get-github-info": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@changesets/get-github-info/-/get-github-info-0.6.0.tgz",
+ "integrity": "sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==",
+ "dev": true,
+ "dependencies": {
+ "dataloader": "^1.4.0",
+ "node-fetch": "^2.5.0"
+ }
+ },
+ "node_modules/@changesets/get-release-plan": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.17.tgz",
+ "integrity": "sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/assemble-release-plan": "^5.2.4",
+ "@changesets/config": "^2.3.1",
+ "@changesets/pre": "^1.0.14",
+ "@changesets/read": "^0.5.9",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3"
+ }
+ },
+ "node_modules/@changesets/get-release-plan/node_modules/@changesets/pre": {
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.14.tgz",
+ "integrity": "sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/errors": "^0.1.4",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "fs-extra": "^7.0.1"
+ }
+ },
+ "node_modules/@changesets/get-release-plan/node_modules/@changesets/read": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.5.9.tgz",
+ "integrity": "sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/git": "^2.0.0",
+ "@changesets/logger": "^0.0.5",
+ "@changesets/parse": "^0.3.16",
+ "@changesets/types": "^5.2.1",
+ "chalk": "^2.1.0",
+ "fs-extra": "^7.0.1",
+ "p-filter": "^2.1.0"
+ }
+ },
+ "node_modules/@changesets/get-version-range-type": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.3.2.tgz",
+ "integrity": "sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==",
+ "dev": true
+ },
+ "node_modules/@changesets/git": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@changesets/git/-/git-2.0.0.tgz",
+ "integrity": "sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/errors": "^0.1.4",
+ "@changesets/types": "^5.2.1",
+ "@manypkg/get-packages": "^1.1.3",
+ "is-subdir": "^1.1.1",
+ "micromatch": "^4.0.2",
+ "spawndamnit": "^2.0.0"
+ }
+ },
+ "node_modules/@changesets/logger": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.0.5.tgz",
+ "integrity": "sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^2.1.0"
+ }
+ },
+ "node_modules/@changesets/parse": {
+ "version": "0.3.16",
+ "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.16.tgz",
+ "integrity": "sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==",
+ "dev": true,
+ "dependencies": {
+ "@changesets/types": "^5.2.1",
+ "js-yaml": "^3.13.1"
+ }
+ },
+ "node_modules/@changesets/pre": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.0.tgz",
+ "integrity": "sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/errors": "^0.2.0",
+ "@changesets/types": "^6.0.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "fs-extra": "^7.0.1"
+ }
+ },
+ "node_modules/@changesets/pre/node_modules/@changesets/errors": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz",
+ "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==",
+ "dev": true,
+ "dependencies": {
+ "extendable-error": "^0.1.5"
+ }
+ },
+ "node_modules/@changesets/pre/node_modules/@changesets/types": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.0.0.tgz",
+ "integrity": "sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==",
+ "dev": true
+ },
+ "node_modules/@changesets/read": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.0.tgz",
+ "integrity": "sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/git": "^3.0.0",
+ "@changesets/logger": "^0.1.0",
+ "@changesets/parse": "^0.4.0",
+ "@changesets/types": "^6.0.0",
+ "chalk": "^2.1.0",
+ "fs-extra": "^7.0.1",
+ "p-filter": "^2.1.0"
+ }
+ },
+ "node_modules/@changesets/read/node_modules/@changesets/errors": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz",
+ "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==",
+ "dev": true,
+ "dependencies": {
+ "extendable-error": "^0.1.5"
+ }
+ },
+ "node_modules/@changesets/read/node_modules/@changesets/git": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.0.tgz",
+ "integrity": "sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/errors": "^0.2.0",
+ "@changesets/types": "^6.0.0",
+ "@manypkg/get-packages": "^1.1.3",
+ "is-subdir": "^1.1.1",
+ "micromatch": "^4.0.2",
+ "spawndamnit": "^2.0.0"
+ }
+ },
+ "node_modules/@changesets/read/node_modules/@changesets/logger": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.0.tgz",
+ "integrity": "sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^2.1.0"
+ }
+ },
+ "node_modules/@changesets/read/node_modules/@changesets/parse": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.0.tgz",
+ "integrity": "sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==",
+ "dev": true,
+ "dependencies": {
+ "@changesets/types": "^6.0.0",
+ "js-yaml": "^3.13.1"
+ }
+ },
+ "node_modules/@changesets/read/node_modules/@changesets/types": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.0.0.tgz",
+ "integrity": "sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==",
+ "dev": true
+ },
+ "node_modules/@changesets/types": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-5.2.1.tgz",
+ "integrity": "sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==",
+ "dev": true
+ },
+ "node_modules/@changesets/write": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.2.3.tgz",
+ "integrity": "sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.20.1",
+ "@changesets/types": "^5.2.1",
+ "fs-extra": "^7.0.1",
+ "human-id": "^1.0.2",
+ "prettier": "^2.7.1"
+ }
+ },
+ "node_modules/@changesets/write/node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
+ "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/compat": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.1.tgz",
+ "integrity": "sha512-JbHG2TWuCeNzh87fXo+/46Z1LEo9DBA9T188d0fZgGxAD+cNyS6sx9fdiyxjGPBMyQVRlCutTByZ6a5+YMkF7g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "peerDependencies": {
+ "eslint": "^9.10.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz",
+ "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.4",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz",
+ "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
+ "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.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"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.13.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz",
+ "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz",
+ "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz",
+ "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@ethereumjs/rlp": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz",
+ "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==",
+ "dev": true,
+ "bin": {
+ "rlp": "bin/rlp"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@ethereumjs/util": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz",
+ "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==",
+ "dev": true,
+ "dependencies": {
+ "@ethereumjs/rlp": "^4.0.1",
+ "ethereum-cryptography": "^2.0.0",
+ "micro-ftch": "^0.3.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz",
+ "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==",
+ "dev": true,
+ "dependencies": {
+ "@noble/curves": "1.1.0",
+ "@noble/hashes": "1.3.1",
+ "@scure/bip32": "1.3.1",
+ "@scure/bip39": "1.2.1"
+ }
+ },
+ "node_modules/@ethersproject/abi": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz",
+ "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/address": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/hash": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/strings": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/abstract-provider": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz",
+ "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/networks": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/transactions": "^5.7.0",
+ "@ethersproject/web": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/abstract-signer": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz",
+ "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/abstract-provider": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/address": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz",
+ "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/rlp": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/base64": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz",
+ "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/bignumber": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz",
+ "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "bn.js": "^5.2.1"
+ }
+ },
+ "node_modules/@ethersproject/bignumber/node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/@ethersproject/bytes": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz",
+ "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/constants": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz",
+ "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/hash": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz",
+ "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/abstract-signer": "^5.7.0",
+ "@ethersproject/address": "^5.7.0",
+ "@ethersproject/base64": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/strings": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/keccak256": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz",
+ "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "js-sha3": "0.8.0"
+ }
+ },
+ "node_modules/@ethersproject/logger": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz",
+ "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ]
+ },
+ "node_modules/@ethersproject/networks": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz",
+ "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/properties": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz",
+ "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/rlp": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz",
+ "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/signing-key": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz",
+ "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "bn.js": "^5.2.1",
+ "elliptic": "6.5.4",
+ "hash.js": "1.1.7"
+ }
+ },
+ "node_modules/@ethersproject/signing-key/node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/@ethersproject/strings": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz",
+ "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/transactions": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz",
+ "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/address": "^5.7.0",
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/rlp": "^5.7.0",
+ "@ethersproject/signing-key": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/units": {
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz",
+ "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/bignumber": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0"
+ }
+ },
+ "node_modules/@ethersproject/web": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz",
+ "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "dependencies": {
+ "@ethersproject/base64": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/logger": "^5.7.0",
+ "@ethersproject/properties": "^5.7.0",
+ "@ethersproject/strings": "^5.7.0"
+ }
+ },
+ "node_modules/@fastify/busboy": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
+ "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@frangio/servbot": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@frangio/servbot/-/servbot-0.2.5.tgz",
+ "integrity": "sha512-ogja4iAPZ1VwM5MU3C1ZhB88358F0PGbmSTGOkIZwOyLaDoMHIqOVCnavHjR7DV5h+oAI4Z4KDqlam3myQUrmg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.x",
+ "pnpm": "7.5.1"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz",
+ "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.5",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz",
+ "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.0",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@isaacs/balanced-match": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
+ "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@isaacs/brace-expansion": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
+ "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@isaacs/balanced-match": "^4.0.1"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@manypkg/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "@types/node": "^12.7.1",
+ "find-up": "^4.1.0",
+ "fs-extra": "^8.1.0"
+ }
+ },
+ "node_modules/@manypkg/find-root/node_modules/@types/node": {
+ "version": "12.20.55",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz",
+ "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==",
+ "dev": true
+ },
+ "node_modules/@manypkg/find-root/node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/@manypkg/get-packages": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz",
+ "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "@changesets/types": "^4.0.1",
+ "@manypkg/find-root": "^1.1.0",
+ "fs-extra": "^8.1.0",
+ "globby": "^11.0.0",
+ "read-yaml-file": "^1.1.0"
+ }
+ },
+ "node_modules/@manypkg/get-packages/node_modules/@changesets/types": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz",
+ "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==",
+ "dev": true
+ },
+ "node_modules/@manypkg/get-packages/node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/@metamask/eth-sig-util": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz",
+ "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==",
+ "dev": true,
+ "dependencies": {
+ "ethereumjs-abi": "^0.6.8",
+ "ethereumjs-util": "^6.2.1",
+ "ethjs-util": "^0.1.6",
+ "tweetnacl": "^1.0.3",
+ "tweetnacl-util": "^0.15.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": {
+ "version": "4.11.6",
+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
+ "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz",
+ "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==",
+ "dev": true,
+ "dependencies": {
+ "@types/bn.js": "^4.11.3",
+ "bn.js": "^4.11.0",
+ "create-hash": "^1.1.2",
+ "elliptic": "^6.5.2",
+ "ethereum-cryptography": "^0.1.3",
+ "ethjs-util": "0.1.6",
+ "rlp": "^2.2.3"
+ }
+ },
+ "node_modules/@noble/ciphers": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz",
+ "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/curves": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
+ "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "1.3.1"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
+ "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@noble/secp256k1": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
+ "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nomicfoundation/edr": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.3.tgz",
+ "integrity": "sha512-zP+e+3B1nEUx6bW5BPnIzCQbkhmYfdMBJdiVggTqqTfAA82sOkdOG7wsOMcz5qF3fYfx/irNRM1kgc9HVFIbpQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 18"
+ },
+ "optionalDependencies": {
+ "@nomicfoundation/edr-darwin-arm64": "0.3.3",
+ "@nomicfoundation/edr-darwin-x64": "0.3.3",
+ "@nomicfoundation/edr-linux-arm64-gnu": "0.3.3",
+ "@nomicfoundation/edr-linux-arm64-musl": "0.3.3",
+ "@nomicfoundation/edr-linux-x64-gnu": "0.3.3",
+ "@nomicfoundation/edr-linux-x64-musl": "0.3.3",
+ "@nomicfoundation/edr-win32-arm64-msvc": "0.3.3",
+ "@nomicfoundation/edr-win32-ia32-msvc": "0.3.3",
+ "@nomicfoundation/edr-win32-x64-msvc": "0.3.3"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-darwin-arm64": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.3.tgz",
+ "integrity": "sha512-E9VGsUD+1Ga4mn/5ooHsMi8JEfhZbKP6CXN/BhJ8kXbIC10NqTD1RuhCKGRtYq4vqH/3Nfq25Xg8E8RWOF4KBQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-darwin-x64": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.3.tgz",
+ "integrity": "sha512-vkZXZ1ydPg+Ijb2iyqENA+KCkxGTCUWG5itCSliiA0Li2YE7ujDMGhheEpFp1WVlZadviz0bfk1rZXbCqlirpg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-arm64-gnu": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.3.tgz",
+ "integrity": "sha512-gdIg0Yj1qqS9wVuywc5B/+DqKylfUGB6/CQn/shMqwAfsAVAVpchkhy66PR+REEx7fh/GkNctxLlENXPeLzDiA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-arm64-musl": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.3.tgz",
+ "integrity": "sha512-AXZ08MFvhNeBZbOBNmz1SJ/DMrMOE2mHEJtaNnsctlxIunjxfrWww4q+WXB34jbr9iaVYYlPsaWe5sueuw6s3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-x64-gnu": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.3.tgz",
+ "integrity": "sha512-xElOs1U+E6lBLtv1mnJ+E8nr2MxZgKiLo8bZAgBboy9odYtmkDVwhMjtsFKSuZbGxFtsSyGRT4cXw3JAbtUDeA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-linux-x64-musl": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.3.tgz",
+ "integrity": "sha512-2Fe6gwm1RAGQ/PfMYiaSba2OrFp8zzYWh+am9lYObOFjV9D+A1zhIzfy0UC74glPks5eV8eY4pBPrVR042m2Nw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-win32-arm64-msvc": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-arm64-msvc/-/edr-win32-arm64-msvc-0.3.3.tgz",
+ "integrity": "sha512-8NHyxIsFrl0ufSQ/ErqF2lKIa/gz1gaaa1a2vKkDEqvqCUcPhBTYhA5NHgTPhLETFTnCFr0z+YbctFCyjh4qrA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-win32-ia32-msvc": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-ia32-msvc/-/edr-win32-ia32-msvc-0.3.3.tgz",
+ "integrity": "sha512-0F6hM0kGia4dQVb/kauho9JcP1ozWisY2/She+ISR5ceuhzmAwQJluM0g+0TYDME0LtxBxiMPq/yPiZMQeq31w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/edr-win32-x64-msvc": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.3.tgz",
+ "integrity": "sha512-d75q1uaMb6z9i+GQZoblbOfFBvlBnWc+5rB13UWRkCOJSnoYwyFWhGJx5GeM59gC7aIblc5VD9qOAhHuvM9N+w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-common": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz",
+ "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==",
+ "dev": true,
+ "dependencies": {
+ "@nomicfoundation/ethereumjs-util": "9.0.4"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-rlp": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz",
+ "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==",
+ "dev": true,
+ "bin": {
+ "rlp": "bin/rlp.cjs"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-tx": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz",
+ "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==",
+ "dev": true,
+ "dependencies": {
+ "@nomicfoundation/ethereumjs-common": "4.0.4",
+ "@nomicfoundation/ethereumjs-rlp": "5.0.4",
+ "@nomicfoundation/ethereumjs-util": "9.0.4",
+ "ethereum-cryptography": "0.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "c-kzg": "^2.1.2"
+ },
+ "peerDependenciesMeta": {
+ "c-kzg": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nomicfoundation/ethereumjs-util": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz",
+ "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==",
+ "dev": true,
+ "dependencies": {
+ "@nomicfoundation/ethereumjs-rlp": "5.0.4",
+ "ethereum-cryptography": "0.1.3"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "c-kzg": "^2.1.2"
+ },
+ "peerDependenciesMeta": {
+ "c-kzg": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@nomicfoundation/hardhat-chai-matchers": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.6.tgz",
+ "integrity": "sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/chai-as-promised": "^7.1.3",
+ "chai-as-promised": "^7.1.1",
+ "deep-eql": "^4.0.1",
+ "ordinal": "^1.0.3"
+ },
+ "peerDependencies": {
+ "@nomicfoundation/hardhat-ethers": "^3.0.0",
+ "chai": "^4.2.0",
+ "ethers": "^6.1.0",
+ "hardhat": "^2.9.4"
+ }
+ },
+ "node_modules/@nomicfoundation/hardhat-ethers": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.4.tgz",
+ "integrity": "sha512-k9qbLoY7qn6C6Y1LI0gk2kyHXil2Tauj4kGzQ8pgxYXIGw8lWn8tuuL72E11CrlKaXRUvOgF0EXrv/msPI2SbA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "lodash.isequal": "^4.5.0"
+ },
+ "peerDependencies": {
+ "ethers": "^6.1.0",
+ "hardhat": "^2.0.0"
+ }
+ },
+ "node_modules/@nomicfoundation/hardhat-network-helpers": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.9.tgz",
+ "integrity": "sha512-OXWCv0cHpwLUO2u7bFxBna6dQtCC2Gg/aN/KtJLO7gmuuA28vgmVKYFRCDUqrbjujzgfwQ2aKyZ9Y3vSmDqS7Q==",
+ "dev": true,
+ "dependencies": {
+ "ethereumjs-util": "^7.1.4"
+ },
+ "peerDependencies": {
+ "hardhat": "^2.9.5"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz",
+ "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ },
+ "optionalDependencies": {
+ "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.1",
+ "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.1"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz",
+ "integrity": "sha512-KcTodaQw8ivDZyF+D76FokN/HdpgGpfjc/gFCImdLUyqB6eSWVaZPazMbeAjmfhx3R0zm/NYVzxwAokFKgrc0w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.1.tgz",
+ "integrity": "sha512-XhQG4BaJE6cIbjAVtzGOGbK3sn1BO9W29uhk9J8y8fZF1DYz0Doj8QDMfpMu+A6TjPDs61lbsmeYodIDnfveSA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.1.tgz",
+ "integrity": "sha512-GHF1VKRdHW3G8CndkwdaeLkVBi5A9u2jwtlS7SLhBc8b5U/GcoL39Q+1CSO3hYqePNP+eV5YI7Zgm0ea6kMHoA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.1.tgz",
+ "integrity": "sha512-g4Cv2fO37ZsUENQ2vwPnZc2zRenHyAxHcyBjKcjaSmmkKrFr64yvzeNO8S3GBFCo90rfochLs99wFVGT/0owpg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.1.tgz",
+ "integrity": "sha512-WJ3CE5Oek25OGE3WwzK7oaopY8xMw9Lhb0mlYuJl/maZVo+WtP36XoQTb7bW/i8aAdHW5Z+BqrHMux23pvxG3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.1.tgz",
+ "integrity": "sha512-5WN7leSr5fkUBBjE4f3wKENUy9HQStu7HmWqbtknfXkkil+eNWiBV275IOlpXku7v3uLsXTOKpnnGHJYI2qsdA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.1.tgz",
+ "integrity": "sha512-KdYMkJOq0SYPQMmErv/63CwGwMm5XHenEna9X9aB8mQmhDBrYrlAOSsIPgFCUSL0hjxE3xHP65/EPXR/InD2+w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.1.tgz",
+ "integrity": "sha512-VFZASBfl4qiBYwW5xeY20exWhmv6ww9sWu/krWSesv3q5hA0o1JuzmPHR4LPN6SUZj5vcqci0O6JOL8BPw+APg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.1.tgz",
+ "integrity": "sha512-JnFkYuyCSA70j6Si6cS1A9Gh1aHTEb8kOTBApp/c7NRTFGNMH8eaInKlyuuiIbvYFhlXW4LicqyYuWNNq9hkpQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.1.tgz",
+ "integrity": "sha512-HrVJr6+WjIXGnw3Q9u6KQcbZCtk0caVWhCdFADySvRyUxJ8PnzlaP+MhwNE8oyT8OZ6ejHBRrrgjSqDCFXGirw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@openzeppelin/docs-utils": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@openzeppelin/docs-utils/-/docs-utils-0.1.5.tgz",
+ "integrity": "sha512-GfqXArKmdq8rv+hsP+g8uS1VEkvMIzWs31dCONffzmqFwJ+MOsaNQNZNXQnLRgUkzk8i5mTNDjJuxDy+aBZImQ==",
+ "dev": true,
+ "dependencies": {
+ "@frangio/servbot": "^0.2.5",
+ "chalk": "^3.0.0",
+ "chokidar": "^3.5.3",
+ "env-paths": "^2.2.0",
+ "find-up": "^4.1.0",
+ "is-port-reachable": "^3.0.0",
+ "js-yaml": "^3.13.1",
+ "lodash.startcase": "^4.4.0",
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "oz-docs": "oz-docs.js"
+ }
+ },
+ "node_modules/@openzeppelin/docs-utils/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@openzeppelin/docs-utils/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@openzeppelin/docs-utils/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@openzeppelin/docs-utils/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@openzeppelin/docs-utils/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@openzeppelin/docs-utils/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@openzeppelin/merkle-tree": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@openzeppelin/merkle-tree/-/merkle-tree-1.0.7.tgz",
+ "integrity": "sha512-i93t0YYv6ZxTCYU3CdO5Q+DXK0JH10A4dCBOMlzYbX+ujTXm+k1lXiEyVqmf94t3sqmv8sm/XT5zTa0+efnPgQ==",
+ "dev": true,
+ "dependencies": {
+ "@ethersproject/abi": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/constants": "^5.7.0",
+ "@ethersproject/keccak256": "^5.7.0"
+ }
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler": {
+ "version": "0.3.32",
+ "resolved": "https://registry.npmjs.org/@openzeppelin/upgrade-safe-transpiler/-/upgrade-safe-transpiler-0.3.32.tgz",
+ "integrity": "sha512-ypgj6MXXcDG0dOuMwENXt0H4atCtCsPgpDgWZYewb2egfUCMpj6d2GO4pcNZgdn1zYsmUHfm5ZA/Nga/8qkdKA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.0",
+ "compare-versions": "^6.0.0",
+ "ethereum-cryptography": "^2.0.0",
+ "lodash": "^4.17.20",
+ "minimatch": "^9.0.0",
+ "minimist": "^1.2.5",
+ "solidity-ast": "^0.4.51"
+ },
+ "bin": {
+ "upgrade-safe-transpiler": "dist/cli.js"
+ }
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler/node_modules/ethereum-cryptography": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz",
+ "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==",
+ "dev": true,
+ "dependencies": {
+ "@noble/curves": "1.1.0",
+ "@noble/hashes": "1.3.1",
+ "@scure/bip32": "1.3.1",
+ "@scure/bip39": "1.2.1"
+ }
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@openzeppelin/upgrade-safe-transpiler/node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@openzeppelin/upgrades-core": {
+ "version": "1.29.0",
+ "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.29.0.tgz",
+ "integrity": "sha512-csZvAMNqUJjMDNBPbaXcV9Nlo4oagMD/HkOBHTpYbBTpnmUhwPVHOMv+Rl0RatBdLHuGc6hw88h80k5PWkEeWw==",
+ "dev": true,
+ "dependencies": {
+ "cbor": "^9.0.0",
+ "chalk": "^4.1.0",
+ "compare-versions": "^6.0.0",
+ "debug": "^4.1.1",
+ "ethereumjs-util": "^7.0.3",
+ "minimist": "^1.2.7",
+ "proper-lockfile": "^4.1.1",
+ "solidity-ast": "^0.4.26"
+ },
+ "bin": {
+ "openzeppelin-upgrades-core": "dist/cli/cli.js"
+ }
+ },
+ "node_modules/@openzeppelin/upgrades-core/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@openzeppelin/upgrades-core/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@openzeppelin/upgrades-core/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@openzeppelin/upgrades-core/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/@openzeppelin/upgrades-core/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@openzeppelin/upgrades-core/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@pnpm/config.env-replace": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz",
+ "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22.0"
+ }
+ },
+ "node_modules/@pnpm/network.ca-file": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz",
+ "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "4.2.10"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ }
+ },
+ "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/@pnpm/npm-conf": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz",
+ "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==",
+ "dev": true,
+ "dependencies": {
+ "@pnpm/config.env-replace": "^1.1.0",
+ "@pnpm/network.ca-file": "^1.0.1",
+ "config-chain": "^1.1.11"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@scure/base": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz",
+ "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==",
+ "dev": true,
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip32": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
+ "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
+ "dev": true,
+ "dependencies": {
+ "@noble/curves": "~1.1.0",
+ "@noble/hashes": "~1.3.1",
+ "@scure/base": "~1.1.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@scure/bip39": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
+ "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "~1.3.0",
+ "@scure/base": "~1.1.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@sentry/core": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz",
+ "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/hub": "5.30.0",
+ "@sentry/minimal": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/hub": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz",
+ "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/minimal": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz",
+ "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/hub": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/node": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz",
+ "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/core": "5.30.0",
+ "@sentry/hub": "5.30.0",
+ "@sentry/tracing": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "cookie": "^0.4.1",
+ "https-proxy-agent": "^5.0.0",
+ "lru_map": "^0.3.3",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/tracing": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz",
+ "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/hub": "5.30.0",
+ "@sentry/minimal": "5.30.0",
+ "@sentry/types": "5.30.0",
+ "@sentry/utils": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/types": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz",
+ "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sentry/utils": {
+ "version": "5.30.0",
+ "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz",
+ "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==",
+ "dev": true,
+ "dependencies": {
+ "@sentry/types": "5.30.0",
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz",
+ "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "node_modules/@solidity-parser/parser": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz",
+ "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==",
+ "dev": true
+ },
+ "node_modules/@szmarczak/http-timer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
+ "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
+ "dev": true,
+ "dependencies": {
+ "defer-to-connect": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/@types/bn.js": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.2.tgz",
+ "integrity": "sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/chai": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.6.tgz",
+ "integrity": "sha512-VOVRLM1mBxIRxydiViqPcKn6MIxZytrbMpd6RJLIWKxUNr3zux8no0Oc7kJx0WAPIitgZ0gkrDS+btlqQpubpw==",
+ "dev": true
+ },
+ "node_modules/@types/chai-as-promised": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.6.tgz",
+ "integrity": "sha512-cQLhk8fFarRVZAXUQV1xEnZgMoPxqKojBvRkqPCKPQCzEhpbbSKl1Uu75kDng7k5Ln6LQLUmNBjLlFthCgm1NA==",
+ "dev": true,
+ "dependencies": {
+ "@types/chai": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/http-cache-semantics": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
+ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
+ "dev": true
+ },
+ "node_modules/@types/is-ci": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/is-ci/-/is-ci-3.0.0.tgz",
+ "integrity": "sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^3.1.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==",
+ "dev": true
+ },
+ "node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
+ "dev": true
+ },
+ "node_modules/@types/minimist": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
+ "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "22.7.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
+ "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
+ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
+ "dev": true
+ },
+ "node_modules/@types/pbkdf2": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz",
+ "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/secp256k1": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz",
+ "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz",
+ "integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==",
+ "dev": true
+ },
+ "node_modules/abbrev": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
+ "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==",
+ "dev": true
+ },
+ "node_modules/abitype": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.2.3.tgz",
+ "integrity": "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/wevm"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.4",
+ "zod": "^3.22.0 || ^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ },
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz",
+ "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/adm-zip": {
+ "version": "0.4.16",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz",
+ "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "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"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.4.2"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "node_modules/ansi-align/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/antlr4": {
+ "version": "4.13.1",
+ "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz",
+ "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/antlr4ts": {
+ "version": "0.5.0-alpha.4",
+ "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz",
+ "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==",
+ "dev": true
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.3.tgz",
+ "integrity": "sha512-kcBubumjciBg4JKp5KTKtI7ec7tRefPk88yjkWJwaVKYd9QfTaxcsOxoMNKd7iBr447zCfDV0z1kOF47umv42g==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0",
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
+ "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-array-buffer": "^3.0.2",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ast-parents": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz",
+ "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==",
+ "dev": true
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
+ "dev": true
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/base-x": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz",
+ "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/better-path-resolve": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz",
+ "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==",
+ "dev": true,
+ "dependencies": {
+ "is-windows": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/blakejs": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz",
+ "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==",
+ "dev": true
+ },
+ "node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/boxen": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz",
+ "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-align": "^3.0.0",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.1.0",
+ "cli-boxes": "^2.2.1",
+ "string-width": "^4.2.2",
+ "type-fest": "^0.20.2",
+ "widest-line": "^3.1.0",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/boxen/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/boxen/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/boxen/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/breakword": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/breakword/-/breakword-1.0.6.tgz",
+ "integrity": "sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==",
+ "dev": true,
+ "dependencies": {
+ "wcwidth": "^1.0.1"
+ }
+ },
+ "node_modules/brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
+ "dev": true
+ },
+ "node_modules/brotli-wasm": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brotli-wasm/-/brotli-wasm-2.0.1.tgz",
+ "integrity": "sha512-+3USgYsC7bzb5yU0/p2HnnynZl0ak0E6uoIm4UW4Aby/8s8HFCq6NCfrrf1E9c3O8OCSzq3oYO1tUVqIi61Nww==",
+ "dev": true
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "node_modules/browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "dependencies": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/bs58": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
+ "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==",
+ "dev": true,
+ "dependencies": {
+ "base-x": "^3.0.2"
+ }
+ },
+ "node_modules/bs58check": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz",
+ "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==",
+ "dev": true,
+ "dependencies": {
+ "bs58": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==",
+ "dev": true
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/cacheable-lookup": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
+ "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/cacheable-request": {
+ "version": "10.2.14",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz",
+ "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-cache-semantics": "^4.0.2",
+ "get-stream": "^6.0.1",
+ "http-cache-semantics": "^4.1.1",
+ "keyv": "^4.5.3",
+ "mimic-response": "^4.0.0",
+ "normalize-url": "^8.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/camelcase-keys": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
+ "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "map-obj": "^4.0.0",
+ "quick-lru": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/camelcase-keys/node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cbor": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz",
+ "integrity": "sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==",
+ "dev": true,
+ "dependencies": {
+ "nofilter": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/chai": {
+ "version": "4.3.8",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.8.tgz",
+ "integrity": "sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==",
+ "dev": true,
+ "dependencies": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^4.1.2",
+ "get-func-name": "^2.0.0",
+ "loupe": "^2.3.1",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chai-as-promised": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz",
+ "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==",
+ "dev": true,
+ "dependencies": {
+ "check-error": "^1.0.2"
+ },
+ "peerDependencies": {
+ "chai": ">= 2.1.2 < 5"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
+ "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cipher-base": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz",
+ "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "safe-buffer": "^5.2.1",
+ "to-buffer": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz",
+ "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/command-exists": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
+ "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
+ "dev": true
+ },
+ "node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/compare-versions": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz",
+ "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
+ "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cosmiconfig": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+ "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+ "dev": true,
+ "dependencies": {
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0",
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cosmiconfig/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/cosmiconfig/node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "node_modules/create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/csv": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/csv/-/csv-5.5.3.tgz",
+ "integrity": "sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==",
+ "dev": true,
+ "dependencies": {
+ "csv-generate": "^3.4.3",
+ "csv-parse": "^4.16.3",
+ "csv-stringify": "^5.6.5",
+ "stream-transform": "^2.1.3"
+ },
+ "engines": {
+ "node": ">= 0.1.90"
+ }
+ },
+ "node_modules/csv-generate": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.4.3.tgz",
+ "integrity": "sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==",
+ "dev": true
+ },
+ "node_modules/csv-parse": {
+ "version": "4.16.3",
+ "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz",
+ "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==",
+ "dev": true
+ },
+ "node_modules/csv-stringify": {
+ "version": "5.6.5",
+ "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.5.tgz",
+ "integrity": "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==",
+ "dev": true
+ },
+ "node_modules/dataloader": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz",
+ "integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==",
+ "dev": true
+ },
+ "node_modules/death": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz",
+ "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decamelize-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
+ "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
+ "dev": true,
+ "dependencies": {
+ "decamelize": "^1.1.0",
+ "map-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decamelize-keys/node_modules/map-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
+ "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-response/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
+ "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dev": true,
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/detect-indent": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+ "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
+ "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/difflib": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz",
+ "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==",
+ "dev": true,
+ "dependencies": {
+ "heap": ">= 0.2.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "8.6.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
+ "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/enquirer": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
+ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz",
+ "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "arraybuffer.prototype.slice": "^1.0.2",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.6",
+ "get-intrinsic": "^1.2.1",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.12",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.5.1",
+ "safe-array-concat": "^1.0.1",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.8",
+ "string.prototype.trimend": "^1.0.7",
+ "string.prototype.trimstart": "^1.0.7",
+ "typed-array-buffer": "^1.0.0",
+ "typed-array-byte-length": "^1.0.0",
+ "typed-array-byte-offset": "^1.0.0",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.11"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+ "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==",
+ "dev": true,
+ "dependencies": {
+ "esprima": "^2.7.1",
+ "estraverse": "^1.9.1",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=0.12.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.2.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/estraverse": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+ "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/escodegen/node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.13.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz",
+ "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.11.0",
+ "@eslint/config-array": "^0.18.0",
+ "@eslint/core": "^0.7.0",
+ "@eslint/eslintrc": "^3.1.0",
+ "@eslint/js": "9.13.0",
+ "@eslint/plugin-kit": "^0.2.0",
+ "@humanfs/node": "^0.16.5",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.3.1",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.1.0",
+ "eslint-visitor-keys": "^4.1.0",
+ "espree": "^10.2.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz",
+ "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz",
+ "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/eslint/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz",
+ "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.12.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz",
+ "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ethereum-bloom-filters": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz",
+ "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==",
+ "dev": true,
+ "dependencies": {
+ "js-sha3": "^0.8.0"
+ }
+ },
+ "node_modules/ethereum-cryptography": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
+ "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/pbkdf2": "^3.0.0",
+ "@types/secp256k1": "^4.0.1",
+ "blakejs": "^1.1.0",
+ "browserify-aes": "^1.2.0",
+ "bs58check": "^2.1.2",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "hash.js": "^1.1.7",
+ "keccak": "^3.0.0",
+ "pbkdf2": "^3.0.17",
+ "randombytes": "^2.1.0",
+ "safe-buffer": "^5.1.2",
+ "scrypt-js": "^3.0.0",
+ "secp256k1": "^4.0.1",
+ "setimmediate": "^1.0.5"
+ }
+ },
+ "node_modules/ethereumjs-abi": {
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz",
+ "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.8",
+ "ethereumjs-util": "^6.0.0"
+ }
+ },
+ "node_modules/ethereumjs-abi/node_modules/@types/bn.js": {
+ "version": "4.11.6",
+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz",
+ "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz",
+ "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==",
+ "dev": true,
+ "dependencies": {
+ "@types/bn.js": "^4.11.3",
+ "bn.js": "^4.11.0",
+ "create-hash": "^1.1.2",
+ "elliptic": "^6.5.2",
+ "ethereum-cryptography": "^0.1.3",
+ "ethjs-util": "0.1.6",
+ "rlp": "^2.2.3"
+ }
+ },
+ "node_modules/ethereumjs-util": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz",
+ "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==",
+ "dev": true,
+ "dependencies": {
+ "@types/bn.js": "^5.1.0",
+ "bn.js": "^5.1.2",
+ "create-hash": "^1.1.2",
+ "ethereum-cryptography": "^0.1.3",
+ "rlp": "^2.2.4"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/ethereumjs-util/node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/ethers": {
+ "version": "6.16.0",
+ "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.16.0.tgz",
+ "integrity": "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/ethers-io/"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.buymeacoffee.com/ricmoo"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@adraffy/ens-normalize": "1.10.1",
+ "@noble/curves": "1.2.0",
+ "@noble/hashes": "1.3.2",
+ "@types/node": "22.7.5",
+ "aes-js": "4.0.0-beta.5",
+ "tslib": "2.7.0",
+ "ws": "8.17.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/ethers/node_modules/@noble/curves": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
+ "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.3.2"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ethers/node_modules/@noble/hashes": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
+ "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ethers/node_modules/aes-js": {
+ "version": "4.0.0-beta.5",
+ "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz",
+ "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==",
+ "dev": true
+ },
+ "node_modules/ethers/node_modules/tslib": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
+ "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "dev": true,
+ "license": "0BSD"
+ },
+ "node_modules/ethers/node_modules/ws": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ethjs-unit": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz",
+ "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "4.11.6",
+ "number-to-bn": "1.7.0"
+ },
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/ethjs-unit/node_modules/bn.js": {
+ "version": "4.11.6",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
+ "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==",
+ "dev": true
+ },
+ "node_modules/ethjs-util": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz",
+ "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==",
+ "dev": true,
+ "dependencies": {
+ "is-hex-prefixed": "1.0.0",
+ "strip-hex-prefix": "1.0.0"
+ },
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "dependencies": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/extendable-error": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz",
+ "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==",
+ "dev": true
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-yarn-workspace-root2": {
+ "version": "1.2.16",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz",
+ "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==",
+ "dev": true,
+ "dependencies": {
+ "micromatch": "^4.0.2",
+ "pkg-dir": "^4.2.0"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data-encoder": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz",
+ "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14.17"
+ }
+ },
+ "node_modules/fp-ts": {
+ "version": "1.19.3",
+ "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz",
+ "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==",
+ "dev": true
+ },
+ "node_modules/fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-func-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
+ "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/ghost-testrpc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz",
+ "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^2.4.2",
+ "node-emoji": "^1.10.0"
+ },
+ "bin": {
+ "testrpc-sc": "index.js"
+ }
+ },
+ "node_modules/glob": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
+ "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "foreground-child": "^3.3.1",
+ "jackspeak": "^4.1.1",
+ "minimatch": "^10.1.1",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
+ "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/brace-expansion": "^5.0.0"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "dev": true,
+ "dependencies": {
+ "global-prefix": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/globals": {
+ "version": "15.11.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz",
+ "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/got": {
+ "version": "12.6.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz",
+ "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==",
+ "dev": true,
+ "dependencies": {
+ "@sindresorhus/is": "^5.2.0",
+ "@szmarczak/http-timer": "^5.0.1",
+ "cacheable-lookup": "^7.0.0",
+ "cacheable-request": "^10.2.8",
+ "decompress-response": "^6.0.0",
+ "form-data-encoder": "^2.1.2",
+ "get-stream": "^6.0.1",
+ "http2-wrapper": "^2.1.10",
+ "lowercase-keys": "^3.0.0",
+ "p-cancelable": "^3.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/got?sponsor=1"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/graphlib": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
+ "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.15"
+ }
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
+ "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/handlebars/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/hard-rejection": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
+ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/hardhat": {
+ "version": "2.22.2",
+ "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.2.tgz",
+ "integrity": "sha512-0xZ7MdCZ5sJem4MrvpQWLR3R3zGDoHw5lsR+pBFimqwagimIOn3bWuZv69KA+veXClwI1s/zpqgwPwiFrd4Dxw==",
+ "dev": true,
+ "dependencies": {
+ "@ethersproject/abi": "^5.1.2",
+ "@metamask/eth-sig-util": "^4.0.0",
+ "@nomicfoundation/edr": "^0.3.1",
+ "@nomicfoundation/ethereumjs-common": "4.0.4",
+ "@nomicfoundation/ethereumjs-tx": "5.0.4",
+ "@nomicfoundation/ethereumjs-util": "9.0.4",
+ "@nomicfoundation/solidity-analyzer": "^0.1.0",
+ "@sentry/node": "^5.18.1",
+ "@types/bn.js": "^5.1.0",
+ "@types/lru-cache": "^5.1.0",
+ "adm-zip": "^0.4.16",
+ "aggregate-error": "^3.0.0",
+ "ansi-escapes": "^4.3.0",
+ "boxen": "^5.1.2",
+ "chalk": "^2.4.2",
+ "chokidar": "^3.4.0",
+ "ci-info": "^2.0.0",
+ "debug": "^4.1.1",
+ "enquirer": "^2.3.0",
+ "env-paths": "^2.2.0",
+ "ethereum-cryptography": "^1.0.3",
+ "ethereumjs-abi": "^0.6.8",
+ "find-up": "^2.1.0",
+ "fp-ts": "1.19.3",
+ "fs-extra": "^7.0.1",
+ "glob": "7.2.0",
+ "immutable": "^4.0.0-rc.12",
+ "io-ts": "1.10.4",
+ "keccak": "^3.0.2",
+ "lodash": "^4.17.11",
+ "mnemonist": "^0.38.0",
+ "mocha": "^10.0.0",
+ "p-map": "^4.0.0",
+ "raw-body": "^2.4.1",
+ "resolve": "1.17.0",
+ "semver": "^6.3.0",
+ "solc": "0.7.3",
+ "source-map-support": "^0.5.13",
+ "stacktrace-parser": "^0.1.10",
+ "tsort": "0.0.1",
+ "undici": "^5.14.0",
+ "uuid": "^8.3.2",
+ "ws": "^7.4.6"
+ },
+ "bin": {
+ "hardhat": "internal/cli/bootstrap.js"
+ },
+ "peerDependencies": {
+ "ts-node": "*",
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "ts-node": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/hardhat-exposed": {
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/hardhat-exposed/-/hardhat-exposed-0.3.15.tgz",
+ "integrity": "sha512-jqxErCnSWGYf4vAkLmh3H3u+IuLuCLw/EVeV13z1JKJMJAd/iO+G283n8T124S/Q2BF/BoA2zgzYAlqXgNyKew==",
+ "dev": true,
+ "dependencies": {
+ "micromatch": "^4.0.4",
+ "solidity-ast": "^0.4.52"
+ },
+ "peerDependencies": {
+ "hardhat": "^2.3.0"
+ }
+ },
+ "node_modules/hardhat-gas-reporter": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-2.3.0.tgz",
+ "integrity": "sha512-ySdA+044xMQv1BlJu5CYXToHzMexKFfIWxlQTBNNoerx1x96+d15IMdN01iQZ/TJ7NH2V5sU73bz77LoS/PEVw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ethersproject/abi": "^5.7.0",
+ "@ethersproject/bytes": "^5.7.0",
+ "@ethersproject/units": "^5.7.0",
+ "@solidity-parser/parser": "^0.20.1",
+ "axios": "^1.6.7",
+ "brotli-wasm": "^2.0.1",
+ "chalk": "4.1.2",
+ "cli-table3": "^0.6.3",
+ "ethereum-cryptography": "^2.1.3",
+ "glob": "^10.3.10",
+ "jsonschema": "^1.4.1",
+ "lodash": "^4.17.21",
+ "markdown-table": "2.0.0",
+ "sha1": "^1.1.1",
+ "viem": "^2.27.0"
+ },
+ "peerDependencies": {
+ "hardhat": "^2.16.0"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/@noble/curves": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz",
+ "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "1.3.3"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/@noble/hashes": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz",
+ "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/@scure/bip32": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz",
+ "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==",
+ "dev": true,
+ "dependencies": {
+ "@noble/curves": "~1.3.0",
+ "@noble/hashes": "~1.3.2",
+ "@scure/base": "~1.1.4"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/@scure/bip39": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz",
+ "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "~1.3.2",
+ "@scure/base": "~1.1.4"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/@solidity-parser/parser": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.2.tgz",
+ "integrity": "sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/cli-table3": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz",
+ "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": "10.* || >= 12.*"
+ },
+ "optionalDependencies": {
+ "@colors/colors": "1.5.0"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/ethereum-cryptography": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz",
+ "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==",
+ "dev": true,
+ "dependencies": {
+ "@noble/curves": "1.3.0",
+ "@noble/hashes": "1.3.3",
+ "@scure/bip32": "1.3.3",
+ "@scure/bip39": "1.2.2"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/markdown-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+ "dev": true,
+ "dependencies": {
+ "repeat-string": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hardhat-gas-reporter/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hardhat-ignore-warnings": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/hardhat-ignore-warnings/-/hardhat-ignore-warnings-0.2.11.tgz",
+ "integrity": "sha512-+nHnRbP6COFZaXE7HAY7TZNE3au5vHe5dkcnyq0XaP07ikT2fJ3NhFY0vn7Deh4Qbz0Z/9Xpnj2ki6Ktgk61pg==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^5.1.0",
+ "node-interval-tree": "^2.0.1",
+ "solidity-comments": "^0.0.2"
+ }
+ },
+ "node_modules/hardhat-ignore-warnings/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/hardhat-ignore-warnings/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/hardhat/node_modules/@noble/hashes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz",
+ "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ]
+ },
+ "node_modules/hardhat/node_modules/@scure/bip32": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz",
+ "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "@noble/hashes": "~1.2.0",
+ "@noble/secp256k1": "~1.7.0",
+ "@scure/base": "~1.1.0"
+ }
+ },
+ "node_modules/hardhat/node_modules/@scure/bip39": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz",
+ "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "@noble/hashes": "~1.2.0",
+ "@scure/base": "~1.1.0"
+ }
+ },
+ "node_modules/hardhat/node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "node_modules/hardhat/node_modules/commander": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz",
+ "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==",
+ "dev": true
+ },
+ "node_modules/hardhat/node_modules/ethereum-cryptography": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz",
+ "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==",
+ "dev": true,
+ "dependencies": {
+ "@noble/hashes": "1.2.0",
+ "@noble/secp256k1": "1.7.1",
+ "@scure/bip32": "1.1.5",
+ "@scure/bip39": "1.1.1"
+ }
+ },
+ "node_modules/hardhat/node_modules/find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hardhat/node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/hardhat/node_modules/jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/hardhat/node_modules/locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hardhat/node_modules/p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hardhat/node_modules/p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hardhat/node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hardhat/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hardhat/node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/hardhat/node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/hardhat/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/hardhat/node_modules/solc": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz",
+ "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==",
+ "dev": true,
+ "dependencies": {
+ "command-exists": "^1.2.8",
+ "commander": "3.0.2",
+ "follow-redirects": "^1.12.1",
+ "fs-extra": "^0.30.0",
+ "js-sha3": "0.8.0",
+ "memorystream": "^0.3.1",
+ "require-from-string": "^2.0.0",
+ "semver": "^5.5.0",
+ "tmp": "0.0.33"
+ },
+ "bin": {
+ "solcjs": "solcjs"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/hardhat/node_modules/solc/node_modules/fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0",
+ "path-is-absolute": "^1.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "node_modules/hardhat/node_modules/solc/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/hardhat/node_modules/undici": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
+ "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@fastify/busboy": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hash-base": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz",
+ "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^2.3.8",
+ "safe-buffer": "^5.2.1",
+ "to-buffer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/hash-base/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hash-base/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/hash-base/node_modules/readable-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hash-base/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/hash-base/node_modules/string_decoder/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/heap": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
+ "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==",
+ "dev": true
+ },
+ "node_modules/hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
+ "dev": true,
+ "dependencies": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+ "dev": true
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dev": true,
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http2-wrapper": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz",
+ "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==",
+ "dev": true,
+ "dependencies": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ }
+ },
+ "node_modules/http2-wrapper/node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/human-id": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/human-id/-/human-id-1.0.2.tgz",
+ "integrity": "sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==",
+ "dev": true
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
+ "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==",
+ "dev": true
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/io-ts": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz",
+ "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==",
+ "dev": true,
+ "dependencies": {
+ "fp-ts": "^1.0.0"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-ci": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
+ "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^3.2.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-hex-prefixed": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz",
+ "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-port-reachable": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-3.1.0.tgz",
+ "integrity": "sha512-vjc0SSRNZ32s9SbZBzGaiP6YVB+xglLShhgZD/FHMZUXBvQWaV9CtzgeVhjccFJrI6RAMV+LX7NYxueW/A8W5A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-subdir": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz",
+ "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==",
+ "dev": true,
+ "dependencies": {
+ "better-path-resolve": "1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/isows": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz",
+ "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "peerDependencies": {
+ "ws": "*"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
+ "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/js-sha3": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
+ "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
+ "dev": true
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonschema": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
+ "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/keccak": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz",
+ "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-addon-api": "^2.0.0",
+ "node-gyp-build": "^4.2.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/latest-version": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz",
+ "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==",
+ "dev": true,
+ "dependencies": {
+ "package-json": "^8.1.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/load-yaml-file": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz",
+ "integrity": "sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.5",
+ "js-yaml": "^3.13.0",
+ "pify": "^4.0.1",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.startcase": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+ "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+ "dev": true
+ },
+ "node_modules/lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-symbols/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/log-symbols/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/log-symbols/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/log-symbols/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
+ "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
+ "dev": true,
+ "dependencies": {
+ "get-func-name": "^2.0.0"
+ }
+ },
+ "node_modules/lowercase-keys": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
+ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lru_map": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
+ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==",
+ "dev": true
+ },
+ "node_modules/lru-cache": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.0.tgz",
+ "integrity": "sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "node_modules/map-obj": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
+ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/memorystream": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
+ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/meow": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz",
+ "integrity": "sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==",
+ "dev": true,
+ "dependencies": {
+ "@types/minimist": "^1.2.0",
+ "camelcase-keys": "^6.2.2",
+ "decamelize-keys": "^1.1.0",
+ "hard-rejection": "^2.1.0",
+ "minimist-options": "^4.0.2",
+ "normalize-package-data": "^2.5.0",
+ "read-pkg-up": "^7.0.1",
+ "redent": "^3.0.0",
+ "trim-newlines": "^3.0.0",
+ "type-fest": "^0.13.1",
+ "yargs-parser": "^18.1.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/meow/node_modules/type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micro-ftch": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz",
+ "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==",
+ "dev": true
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz",
+ "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "node_modules/minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
+ "dev": true
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minimist-options": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
+ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+ "dev": true,
+ "dependencies": {
+ "arrify": "^1.0.1",
+ "is-plain-obj": "^1.1.0",
+ "kind-of": "^6.0.3"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/mixme": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.9.tgz",
+ "integrity": "sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/mnemonist": {
+ "version": "0.38.5",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz",
+ "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==",
+ "dev": true,
+ "dependencies": {
+ "obliterator": "^2.0.0"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "10.8.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
+ "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-colors": "^4.1.3",
+ "browser-stdout": "^1.3.1",
+ "chokidar": "^3.5.3",
+ "debug": "^4.3.5",
+ "diff": "^5.2.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-up": "^5.0.0",
+ "glob": "^8.1.0",
+ "he": "^1.2.0",
+ "js-yaml": "^4.1.0",
+ "log-symbols": "^4.1.0",
+ "minimatch": "^5.1.6",
+ "ms": "^2.1.3",
+ "serialize-javascript": "^6.0.2",
+ "strip-json-comments": "^3.1.1",
+ "supports-color": "^8.1.1",
+ "workerpool": "^6.5.1",
+ "yargs": "^16.2.0",
+ "yargs-parser": "^20.2.9",
+ "yargs-unparser": "^2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/mocha/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/mocha/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/mocha/node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+ "dev": true
+ },
+ "node_modules/node-addon-api": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",
+ "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==",
+ "dev": true
+ },
+ "node_modules/node-emoji": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
+ "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.21"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-gyp-build": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz",
+ "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==",
+ "dev": true,
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
+ "node_modules/node-interval-tree": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/node-interval-tree/-/node-interval-tree-2.1.2.tgz",
+ "integrity": "sha512-bJ9zMDuNGzVQg1xv0bCPzyEDxHgbrx7/xGj6CDokvizZZmastPsOh0JJLuY8wA5q2SfX1TLNMk7XNV8WxbGxzA==",
+ "dev": true,
+ "dependencies": {
+ "shallowequal": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/nofilter": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz",
+ "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.19"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
+ "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ }
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-url": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz",
+ "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/number-to-bn": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz",
+ "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "4.11.6",
+ "strip-hex-prefix": "1.0.0"
+ },
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/number-to-bn/node_modules/bn.js": {
+ "version": "4.11.6",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
+ "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==",
+ "dev": true
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obliterator": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz",
+ "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==",
+ "dev": true
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "dev": true,
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ordinal": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz",
+ "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==",
+ "dev": true
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/outdent": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz",
+ "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==",
+ "dev": true
+ },
+ "node_modules/ox": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/ox/-/ox-0.11.1.tgz",
+ "integrity": "sha512-1l1gOLAqg0S0xiN1dH5nkPna8PucrZgrIJOfS49MLNiMevxu07Iz4ZjuJS9N+xifvT+PsZyIptS7WHM8nC+0+A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@adraffy/ens-normalize": "^1.11.0",
+ "@noble/ciphers": "^1.3.0",
+ "@noble/curves": "1.9.1",
+ "@noble/hashes": "^1.8.0",
+ "@scure/bip32": "^1.7.0",
+ "@scure/bip39": "^1.6.0",
+ "abitype": "^1.2.3",
+ "eventemitter3": "5.0.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ox/node_modules/@adraffy/ens-normalize": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz",
+ "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ox/node_modules/@noble/curves": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz",
+ "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ox/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ox/node_modules/@scure/base": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ox/node_modules/@scure/bip32": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz",
+ "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "~1.9.0",
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/ox/node_modules/@scure/bip39": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz",
+ "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/p-cancelable": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
+ "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.20"
+ }
+ },
+ "node_modules/p-filter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz",
+ "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==",
+ "dev": true,
+ "dependencies": {
+ "p-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-filter/node_modules/p-map": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-json": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz",
+ "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==",
+ "dev": true,
+ "dependencies": {
+ "got": "^12.1.0",
+ "registry-auth-token": "^5.0.1",
+ "registry-url": "^6.0.0",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
+ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-scurry": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+ "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pathval": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/pbkdf2": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz",
+ "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "ripemd160": "^2.0.3",
+ "safe-buffer": "^5.2.1",
+ "sha.js": "^2.4.12",
+ "to-buffer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/preferred-pm": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.1.2.tgz",
+ "integrity": "sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^5.0.0",
+ "find-yarn-workspace-root2": "1.2.16",
+ "path-exists": "^4.0.0",
+ "which-pm": "2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/preferred-pm/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/preferred-pm/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/preferred-pm/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
+ "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-plugin-solidity": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.3.tgz",
+ "integrity": "sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg==",
+ "dev": true,
+ "dependencies": {
+ "@solidity-parser/parser": "^0.16.0",
+ "semver": "^7.3.8",
+ "solidity-comments-extractor": "^0.0.7"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "prettier": ">=2.3.0 || >=3.0.0-alpha.0"
+ }
+ },
+ "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.1.tgz",
+ "integrity": "sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==",
+ "dev": true,
+ "dependencies": {
+ "antlr4ts": "^0.5.0-alpha.4"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/proper-lockfile": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz",
+ "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "retry": "^0.12.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+ "dev": true
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "dev": true
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+ "dev": true
+ },
+ "node_modules/punycode": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz",
+ "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/quick-lru": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
+ "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "dev": true,
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
+ "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
+ "dev": true,
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg-up/node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-yaml-file": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz",
+ "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.5",
+ "js-yaml": "^3.6.1",
+ "pify": "^4.0.1",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/recursive-readdir": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
+ "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "dependencies": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/redent/node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
+ "dev": true
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
+ "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "set-function-name": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/registry-auth-token": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz",
+ "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==",
+ "dev": true,
+ "dependencies": {
+ "@pnpm/npm-conf": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/registry-url": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz",
+ "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==",
+ "dev": true,
+ "dependencies": {
+ "rc": "1.2.8"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "node_modules/resolve": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+ "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
+ "dev": true,
+ "dependencies": {
+ "path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
+ "dev": true
+ },
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/responselike": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
+ "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==",
+ "dev": true,
+ "dependencies": {
+ "lowercase-keys": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.0.tgz",
+ "integrity": "sha512-u+yqhM92LW+89cxUQK0SRyvXYQmyuKHx0jkx4W7KfwLGLqJnQM5031Uv1trE4gB9XEXBM/s6MxKlfW95IidqaA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^11.0.0"
+ },
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/ripemd160": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz",
+ "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hash-base": "^3.1.2",
+ "inherits": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/rlp": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz",
+ "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^5.2.0"
+ },
+ "bin": {
+ "rlp": "bin/rlp"
+ }
+ },
+ "node_modules/rlp/node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
+ "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/sc-istanbul": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz",
+ "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "1.0.x",
+ "async": "1.x",
+ "escodegen": "1.8.x",
+ "esprima": "2.7.x",
+ "glob": "^5.0.15",
+ "handlebars": "^4.0.1",
+ "js-yaml": "3.x",
+ "mkdirp": "0.5.x",
+ "nopt": "3.x",
+ "once": "1.x",
+ "resolve": "1.1.x",
+ "supports-color": "^3.1.0",
+ "which": "^1.1.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "istanbul": "lib/cli.js"
+ }
+ },
+ "node_modules/sc-istanbul/node_modules/esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==",
+ "dev": true,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sc-istanbul/node_modules/glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==",
+ "dev": true,
+ "dependencies": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/sc-istanbul/node_modules/has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sc-istanbul/node_modules/resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==",
+ "dev": true
+ },
+ "node_modules/sc-istanbul/node_modules/supports-color": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
+ "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/sc-istanbul/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/scrypt-js": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz",
+ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==",
+ "dev": true
+ },
+ "node_modules/secp256k1": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz",
+ "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "elliptic": "^6.5.7",
+ "node-addon-api": "^5.0.0",
+ "node-gyp-build": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/secp256k1/node_modules/elliptic": {
+ "version": "6.5.7",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
+ "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/secp256k1/node_modules/node-addon-api": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz",
+ "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==",
+ "dev": true
+ },
+ "node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "dev": true
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
+ "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
+ "dev": true
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true
+ },
+ "node_modules/sha.js": {
+ "version": "2.4.12",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
+ "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
+ "dev": true,
+ "license": "(MIT AND BSD-3-Clause)",
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "safe-buffer": "^5.2.1",
+ "to-buffer": "^1.2.0"
+ },
+ "bin": {
+ "sha.js": "bin.js"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/sha1": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz",
+ "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==",
+ "dev": true,
+ "dependencies": {
+ "charenc": ">= 0.0.1",
+ "crypt": ">= 0.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
+ "dev": true
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shelljs": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+ "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "bin": {
+ "shjs": "bin/shjs"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/shelljs/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smartwrap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/smartwrap/-/smartwrap-2.0.2.tgz",
+ "integrity": "sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==",
+ "dev": true,
+ "dependencies": {
+ "array.prototype.flat": "^1.2.3",
+ "breakword": "^1.0.5",
+ "grapheme-splitter": "^1.0.4",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1",
+ "yargs": "^15.1.0"
+ },
+ "bin": {
+ "smartwrap": "src/terminal-adapter.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/smartwrap/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/smartwrap/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/smartwrap/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/smartwrap/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/smartwrap/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smartwrap/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smartwrap/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/smartwrap/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "dev": true
+ },
+ "node_modules/smartwrap/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/solhint": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.0.tgz",
+ "integrity": "sha512-pSRKkzRsruia6/xa9L5VSyd7dMZkiiTi/aYZcvUQo7KK+S16ojPwIbt2jfjbH5WEJ83grzIIE4WrYQfAxGWh/A==",
+ "dev": true,
+ "dependencies": {
+ "@solidity-parser/parser": "^0.18.0",
+ "ajv": "^6.12.6",
+ "antlr4": "^4.13.1-patch-1",
+ "ast-parents": "^0.0.1",
+ "chalk": "^4.1.2",
+ "commander": "^10.0.0",
+ "cosmiconfig": "^8.0.0",
+ "fast-diff": "^1.2.0",
+ "glob": "^8.0.3",
+ "ignore": "^5.2.4",
+ "js-yaml": "^4.1.0",
+ "latest-version": "^7.0.0",
+ "lodash": "^4.17.21",
+ "pluralize": "^8.0.0",
+ "semver": "^7.5.2",
+ "strip-ansi": "^6.0.1",
+ "table": "^6.8.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "solhint": "solhint.js"
+ },
+ "optionalDependencies": {
+ "prettier": "^2.8.3"
+ }
+ },
+ "node_modules/solhint-plugin-openzeppelin": {
+ "resolved": "scripts/solhint-custom",
+ "link": true
+ },
+ "node_modules/solhint/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/solhint/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/solhint/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/solhint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/solhint/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/solhint/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/solhint/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/solhint/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/solhint/node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/solhint/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/solhint/node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/solhint/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/solidity-ast": {
+ "version": "0.4.52",
+ "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.52.tgz",
+ "integrity": "sha512-iOya9BSiB9jhM8Vf40n8lGELGzwrUc57rl5BhfNtJ5cvAaMvRcNlHeAMNvqJJyjoUnczqRbHqdivEqK89du3Cw==",
+ "dev": true,
+ "dependencies": {
+ "array.prototype.findlast": "^1.2.2"
+ }
+ },
+ "node_modules/solidity-comments": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments/-/solidity-comments-0.0.2.tgz",
+ "integrity": "sha512-G+aK6qtyUfkn1guS8uzqUeua1dURwPlcOjoTYW/TwmXAcE7z/1+oGCfZUdMSe4ZMKklNbVZNiG5ibnF8gkkFfw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ },
+ "optionalDependencies": {
+ "solidity-comments-darwin-arm64": "0.0.2",
+ "solidity-comments-darwin-x64": "0.0.2",
+ "solidity-comments-freebsd-x64": "0.0.2",
+ "solidity-comments-linux-arm64-gnu": "0.0.2",
+ "solidity-comments-linux-arm64-musl": "0.0.2",
+ "solidity-comments-linux-x64-gnu": "0.0.2",
+ "solidity-comments-linux-x64-musl": "0.0.2",
+ "solidity-comments-win32-arm64-msvc": "0.0.2",
+ "solidity-comments-win32-ia32-msvc": "0.0.2",
+ "solidity-comments-win32-x64-msvc": "0.0.2"
+ }
+ },
+ "node_modules/solidity-comments-darwin-arm64": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-darwin-arm64/-/solidity-comments-darwin-arm64-0.0.2.tgz",
+ "integrity": "sha512-HidWkVLSh7v+Vu0CA7oI21GWP/ZY7ro8g8OmIxE8oTqyMwgMbE8F1yc58Sj682Hj199HCZsjmtn1BE4PCbLiGA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-darwin-x64": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-darwin-x64/-/solidity-comments-darwin-x64-0.0.2.tgz",
+ "integrity": "sha512-Zjs0Ruz6faBTPT6fBecUt6qh4CdloT8Bwoc0+qxRoTn9UhYscmbPQkUgQEbS0FQPysYqVzzxJB4h1Ofbf4wwtA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-extractor": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz",
+ "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==",
+ "dev": true
+ },
+ "node_modules/solidity-comments-freebsd-x64": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-freebsd-x64/-/solidity-comments-freebsd-x64-0.0.2.tgz",
+ "integrity": "sha512-8Qe4mpjuAxFSwZJVk7B8gAoLCdbtS412bQzBwk63L8dmlHogvE39iT70aAk3RHUddAppT5RMBunlPUCFYJ3ZTw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-linux-arm64-gnu": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-linux-arm64-gnu/-/solidity-comments-linux-arm64-gnu-0.0.2.tgz",
+ "integrity": "sha512-spkb0MZZnmrP+Wtq4UxP+nyPAVRe82idOjqndolcNR0S9Xvu4ebwq+LvF4HiUgjTDmeiqYiFZQ8T9KGdLSIoIg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-linux-arm64-musl": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-linux-arm64-musl/-/solidity-comments-linux-arm64-musl-0.0.2.tgz",
+ "integrity": "sha512-guCDbHArcjE+JDXYkxx5RZzY1YF6OnAKCo+sTC5fstyW/KGKaQJNPyBNWuwYsQiaEHpvhW1ha537IvlGek8GqA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-linux-x64-gnu": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-linux-x64-gnu/-/solidity-comments-linux-x64-gnu-0.0.2.tgz",
+ "integrity": "sha512-zIqLehBK/g7tvrFmQljrfZXfkEeLt2v6wbe+uFu6kH/qAHZa7ybt8Vc0wYcmjo2U0PeBm15d79ee3AkwbIjFdQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-linux-x64-musl": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-linux-x64-musl/-/solidity-comments-linux-x64-musl-0.0.2.tgz",
+ "integrity": "sha512-R9FeDloVlFGTaVkOlELDVC7+1Tjx5WBPI5L8r0AGOPHK3+jOcRh6sKYpI+VskSPDc3vOO46INkpDgUXrKydlIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-win32-arm64-msvc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-win32-arm64-msvc/-/solidity-comments-win32-arm64-msvc-0.0.2.tgz",
+ "integrity": "sha512-QnWJoCQcJj+rnutULOihN9bixOtYWDdF5Rfz9fpHejL1BtNjdLW1om55XNVHGAHPqBxV4aeQQ6OirKnp9zKsug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-win32-ia32-msvc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-win32-ia32-msvc/-/solidity-comments-win32-ia32-msvc-0.0.2.tgz",
+ "integrity": "sha512-vUg4nADtm/NcOtlIymG23NWJUSuMsvX15nU7ynhGBsdKtt8xhdP3C/zA6vjDk8Jg+FXGQL6IHVQ++g/7rSQi0w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-comments-win32-x64-msvc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/solidity-comments-win32-x64-msvc/-/solidity-comments-win32-x64-msvc-0.0.2.tgz",
+ "integrity": "sha512-36j+KUF4V/y0t3qatHm/LF5sCUCBx2UndxE1kq5bOzh/s+nQgatuyB+Pd5BfuPQHdWu2KaExYe20FlAa6NL7+Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/solidity-coverage": {
+ "version": "0.8.17",
+ "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.17.tgz",
+ "integrity": "sha512-5P8vnB6qVX9tt1MfuONtCTEaEGO/O4WuEidPHIAJjx4sktHHKhO3rFvnE0q8L30nWJPTrcqGQMT7jpE29B2qow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@ethersproject/abi": "^5.0.9",
+ "@solidity-parser/parser": "^0.20.1",
+ "chalk": "^2.4.2",
+ "death": "^1.1.0",
+ "difflib": "^0.2.4",
+ "fs-extra": "^8.1.0",
+ "ghost-testrpc": "^0.0.2",
+ "global-modules": "^2.0.0",
+ "globby": "^10.0.1",
+ "jsonschema": "^1.2.4",
+ "lodash": "^4.17.21",
+ "mocha": "^10.2.0",
+ "node-emoji": "^1.10.0",
+ "pify": "^4.0.1",
+ "recursive-readdir": "^2.2.2",
+ "sc-istanbul": "^0.4.5",
+ "semver": "^7.3.4",
+ "shelljs": "^0.8.3",
+ "web3-utils": "^1.3.6"
+ },
+ "bin": {
+ "solidity-coverage": "plugins/bin.js"
+ },
+ "peerDependencies": {
+ "hardhat": "^2.11.0"
+ }
+ },
+ "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.2.tgz",
+ "integrity": "sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/solidity-coverage/node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/solidity-coverage/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/solidity-coverage/node_modules/globby": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz",
+ "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==",
+ "dev": true,
+ "dependencies": {
+ "@types/glob": "^7.1.1",
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.0.3",
+ "glob": "^7.1.3",
+ "ignore": "^5.1.1",
+ "merge2": "^1.2.3",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/solidity-docgen": {
+ "version": "0.6.0-beta.36",
+ "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.36.tgz",
+ "integrity": "sha512-f/I5G2iJgU1h0XrrjRD0hHMr7C10u276vYvm//rw1TzFcYQ4xTOyAoi9oNAHRU0JU4mY9eTuxdVc2zahdMuhaQ==",
+ "dev": true,
+ "dependencies": {
+ "handlebars": "^4.7.7",
+ "solidity-ast": "^0.4.38"
+ },
+ "peerDependencies": {
+ "hardhat": "^2.8.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+ "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "amdefine": ">=0.0.4"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spawndamnit": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-2.0.0.tgz",
+ "integrity": "sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/spawndamnit/node_modules/cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "node_modules/spawndamnit/node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/spawndamnit/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spawndamnit/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spawndamnit/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/spawndamnit/node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
+ "dev": true
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.15",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz",
+ "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==",
+ "dev": true
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true
+ },
+ "node_modules/stacktrace-parser": {
+ "version": "0.1.10",
+ "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz",
+ "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.7.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/stacktrace-parser/node_modules/type-fest": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
+ "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/stream-transform": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz",
+ "integrity": "sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==",
+ "dev": true,
+ "dependencies": {
+ "mixme": "^0.5.1"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
+ "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
+ "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
+ "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-hex-prefix": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz",
+ "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==",
+ "dev": true,
+ "dependencies": {
+ "is-hex-prefixed": "1.0.0"
+ },
+ "engines": {
+ "node": ">=6.5.0",
+ "npm": ">=3"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/table": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
+ "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/table/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/table/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/table/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/table/node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/table/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/term-size": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
+ "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/to-buffer": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
+ "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "isarray": "^2.0.5",
+ "safe-buffer": "^5.2.1",
+ "typed-array-buffer": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "node_modules/trim-newlines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
+ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/tsort": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz",
+ "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==",
+ "dev": true
+ },
+ "node_modules/tty-table": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/tty-table/-/tty-table-4.2.1.tgz",
+ "integrity": "sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "csv": "^5.5.3",
+ "kleur": "^4.1.5",
+ "smartwrap": "^2.0.2",
+ "strip-ansi": "^6.0.1",
+ "wcwidth": "^1.0.1",
+ "yargs": "^17.7.1"
+ },
+ "bin": {
+ "tty-table": "adapters/terminal-adapter.js"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/tty-table/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/tty-table/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/tty-table/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/tty-table/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/tty-table/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tty-table/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
+ "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
+ "dev": true
+ },
+ "node_modules/tweetnacl-util": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
+ "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
+ "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.17.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
+ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
+ "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/utf8": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
+ "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==",
+ "dev": true
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/viem": {
+ "version": "2.43.5",
+ "resolved": "https://registry.npmjs.org/viem/-/viem-2.43.5.tgz",
+ "integrity": "sha512-QuJpuEMEPM3EreN+vX4mVY68Sci0+zDxozYfbh/WfV+SSy/Gthm74PH8XmitXdty1xY54uTCJ+/Gbbd1IiMPSA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/wevm"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "1.9.1",
+ "@noble/hashes": "1.8.0",
+ "@scure/bip32": "1.7.0",
+ "@scure/bip39": "1.6.0",
+ "abitype": "1.2.3",
+ "isows": "1.0.7",
+ "ox": "0.11.1",
+ "ws": "8.18.3"
+ },
+ "peerDependencies": {
+ "typescript": ">=5.0.4"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/viem/node_modules/@noble/curves": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz",
+ "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "1.8.0"
+ },
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/@scure/base": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz",
+ "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/@scure/bip32": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz",
+ "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/curves": "~1.9.0",
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/@scure/bip39": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz",
+ "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "~1.8.0",
+ "@scure/base": "~1.2.5"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/viem/node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dev": true,
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/web3-utils": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.2.tgz",
+ "integrity": "sha512-TdApdzdse5YR+5GCX/b/vQnhhbj1KSAtfrDtRW7YS0kcWp1gkJsN62gw6GzCaNTeXookB7UrLtmDUuMv65qgow==",
+ "dev": true,
+ "dependencies": {
+ "@ethereumjs/util": "^8.1.0",
+ "bn.js": "^5.2.1",
+ "ethereum-bloom-filters": "^1.0.6",
+ "ethereum-cryptography": "^2.1.2",
+ "ethjs-unit": "0.1.6",
+ "number-to-bn": "1.7.0",
+ "randombytes": "^2.1.0",
+ "utf8": "3.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/web3-utils/node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/web3-utils/node_modules/ethereum-cryptography": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz",
+ "integrity": "sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug==",
+ "dev": true,
+ "dependencies": {
+ "@noble/curves": "1.1.0",
+ "@noble/hashes": "1.3.1",
+ "@scure/bip32": "1.3.1",
+ "@scure/bip39": "1.2.1"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+ "dev": true
+ },
+ "node_modules/which-pm": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-2.0.0.tgz",
+ "integrity": "sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==",
+ "dev": true,
+ "dependencies": {
+ "load-yaml-file": "^0.2.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8.15"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+ "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",
+ "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/widest-line/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/widest-line/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
+ "dev": true
+ },
+ "node_modules/workerpool": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
+ "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yargs-parser/node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "scripts/solhint-custom": {
+ "name": "solhint-plugin-openzeppelin",
+ "version": "0.0.0",
+ "dev": true
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/package.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/package.json
new file mode 100644
index 000000000..2d601f924
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/package.json
@@ -0,0 +1,92 @@
+{
+ "name": "openzeppelin-solidity",
+ "description": "Secure Smart Contract library for Solidity",
+ "version": "5.2.0",
+ "private": true,
+ "files": [
+ "/contracts/**/*.sol",
+ "!/contracts/mocks/**/*"
+ ],
+ "scripts": {
+ "compile": "hardhat compile",
+ "compile:harnesses": "env SRC=./certora/harnesses hardhat compile",
+ "coverage": "scripts/checks/coverage.sh",
+ "docs": "npm run prepare-docs && oz-docs",
+ "docs:watch": "oz-docs watch contracts docs/templates docs/config.js",
+ "prepare": "scripts/prepare.sh",
+ "prepare-docs": "scripts/prepare-docs.sh",
+ "lint": "npm run lint:js && npm run lint:sol",
+ "lint:fix": "npm run lint:js:fix && npm run lint:sol:fix",
+ "lint:js": "prettier --log-level warn --ignore-path .gitignore '**/*.{js,ts}' --check && eslint .",
+ "lint:js:fix": "prettier --log-level warn --ignore-path .gitignore '**/*.{js,ts}' --write && eslint . --fix",
+ "lint:sol": "prettier --log-level warn --ignore-path .gitignore '{contracts,test}/**/*.sol' --check && solhint '{contracts,test}/**/*.sol'",
+ "lint:sol:fix": "prettier --log-level warn --ignore-path .gitignore '{contracts,test}/**/*.sol' --write",
+ "clean": "hardhat clean && rimraf build contracts/build",
+ "prepack": "scripts/prepack.sh",
+ "generate": "scripts/generate/run.js",
+ "version": "scripts/release/version.sh",
+ "test": "hardhat test",
+ "test:generation": "scripts/checks/generation.sh",
+ "test:inheritance": "scripts/checks/inheritance-ordering.js artifacts/build-info/*",
+ "test:pragma": "scripts/checks/pragma-consistency.js artifacts/build-info/*",
+ "gas-report": "env ENABLE_GAS_REPORT=true npm run test",
+ "slither": "npm run clean && slither ."
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/OpenZeppelin/openzeppelin-contracts.git"
+ },
+ "keywords": [
+ "solidity",
+ "ethereum",
+ "smart",
+ "contracts",
+ "security",
+ "zeppelin"
+ ],
+ "author": "OpenZeppelin Community ",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/OpenZeppelin/openzeppelin-contracts/issues"
+ },
+ "homepage": "https://openzeppelin.com/contracts/",
+ "devDependencies": {
+ "@changesets/changelog-github": "^0.5.0",
+ "@changesets/cli": "^2.26.0",
+ "@changesets/pre": "^2.0.0",
+ "@changesets/read": "^0.6.0",
+ "@eslint/compat": "^1.2.1",
+ "@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
+ "@nomicfoundation/hardhat-ethers": "^3.0.4",
+ "@nomicfoundation/hardhat-network-helpers": "^1.0.3",
+ "@openzeppelin/docs-utils": "^0.1.5",
+ "@openzeppelin/merkle-tree": "^1.0.7",
+ "@openzeppelin/upgrade-safe-transpiler": "^0.3.32",
+ "@openzeppelin/upgrades-core": "^1.20.6",
+ "chai": "^4.2.0",
+ "eslint": "^9.0.0",
+ "eslint-config-prettier": "^9.0.0",
+ "ethers": "^6.16.0",
+ "globals": "^15.3.0",
+ "glob": "^11.1.0",
+ "graphlib": "^2.1.8",
+ "hardhat": "^2.22.2",
+ "hardhat-exposed": "^0.3.15",
+ "hardhat-gas-reporter": "^2.3.0",
+ "hardhat-ignore-warnings": "^0.2.11",
+ "lodash.startcase": "^4.4.0",
+ "micromatch": "^4.0.8",
+ "p-limit": "^3.1.0",
+ "prettier": "^3.0.0",
+ "prettier-plugin-solidity": "^1.1.0",
+ "rimraf": "^6.0.0",
+ "semver": "^7.3.5",
+ "solhint": "^5.0.0",
+ "solhint-plugin-openzeppelin": "file:scripts/solhint-custom",
+ "solidity-ast": "^0.4.50",
+ "solidity-coverage": "^0.8.17",
+ "solidity-docgen": "^0.6.0-beta.29",
+ "undici": "^6.23.0",
+ "yargs": "^17.0.0"
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/remappings.txt b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/remappings.txt
new file mode 100644
index 000000000..304d1386a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/remappings.txt
@@ -0,0 +1 @@
+@openzeppelin/contracts/=contracts/
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/renovate.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/renovate.json
new file mode 100644
index 000000000..c0b97d8d7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/renovate.json
@@ -0,0 +1,4 @@
+{
+ "extends": ["github>OpenZeppelin/configs"],
+ "labels": ["ignore-changeset"]
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/compare-layout.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/compare-layout.js
new file mode 100644
index 000000000..64ff4398d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/compare-layout.js
@@ -0,0 +1,20 @@
+const fs = require('fs');
+const { getStorageUpgradeReport } = require('@openzeppelin/upgrades-core/dist/storage');
+
+const { ref, head } = require('yargs').argv;
+
+const oldLayout = JSON.parse(fs.readFileSync(ref));
+const newLayout = JSON.parse(fs.readFileSync(head));
+
+for (const name in oldLayout) {
+ if (name in newLayout) {
+ const report = getStorageUpgradeReport(oldLayout[name], newLayout[name], {});
+ if (!report.ok) {
+ console.log(`Storage layout incompatibility found in ${name}:`);
+ console.log(report.explain());
+ process.exitCode = 1;
+ }
+ } else {
+ console.log(`WARNING: ${name} is missing from the current branch`);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/compareGasReports.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/compareGasReports.js
new file mode 100644
index 000000000..2c7b4dc24
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/compareGasReports.js
@@ -0,0 +1,247 @@
+#!/usr/bin/env node
+
+const fs = require('fs');
+const chalk = require('chalk');
+const { argv } = require('yargs')
+ .env()
+ .options({
+ style: {
+ type: 'string',
+ choices: ['shell', 'markdown'],
+ default: 'shell',
+ },
+ hideEqual: {
+ type: 'boolean',
+ default: true,
+ },
+ strictTesting: {
+ type: 'boolean',
+ default: false,
+ },
+ });
+
+// Deduce base tx cost from the percentage denominator
+const BASE_TX_COST = 21000;
+
+// Utilities
+function sum(...args) {
+ return args.reduce((a, b) => a + b, 0);
+}
+
+function average(...args) {
+ return sum(...args) / args.length;
+}
+
+function variation(current, previous, offset = 0) {
+ return {
+ value: current,
+ delta: current - previous,
+ prcnt: (100 * (current - previous)) / (previous - offset),
+ };
+}
+
+// Report class
+class Report {
+ // Read report file
+ static load(filepath) {
+ return JSON.parse(fs.readFileSync(filepath, 'utf8'));
+ }
+
+ // Compare two reports
+ static compare(update, ref, opts = { hideEqual: true, strictTesting: false }) {
+ if (JSON.stringify(update.options?.solcInfo) !== JSON.stringify(ref.options?.solcInfo)) {
+ console.warn('WARNING: Reports produced with non matching metadata');
+ }
+
+ // gasReporter 1.0.0 uses ".info", but 2.0.0 uses ".data"
+ const updateInfo = update.info ?? update.data;
+ const refInfo = ref.info ?? ref.data;
+
+ const deployments = updateInfo.deployments
+ .map(contract =>
+ Object.assign(contract, { previousVersion: refInfo.deployments.find(({ name }) => name === contract.name) }),
+ )
+ .filter(contract => contract.gasData?.length && contract.previousVersion?.gasData?.length)
+ .flatMap(contract => [
+ {
+ contract: contract.name,
+ method: '[bytecode length]',
+ avg: variation(contract.bytecode.length / 2 - 1, contract.previousVersion.bytecode.length / 2 - 1),
+ },
+ {
+ contract: contract.name,
+ method: '[construction cost]',
+ avg: variation(
+ ...[contract.gasData, contract.previousVersion.gasData].map(x => Math.round(average(...x))),
+ BASE_TX_COST,
+ ),
+ },
+ ])
+ .sort((a, b) => `${a.contract}:${a.method}`.localeCompare(`${b.contract}:${b.method}`));
+
+ const methods = Object.keys(updateInfo.methods)
+ .filter(key => refInfo.methods[key])
+ .filter(key => updateInfo.methods[key].numberOfCalls > 0)
+ .filter(
+ key => !opts.strictTesting || updateInfo.methods[key].numberOfCalls === refInfo.methods[key].numberOfCalls,
+ )
+ .map(key => ({
+ contract: refInfo.methods[key].contract,
+ method: refInfo.methods[key].fnSig,
+ min: variation(...[updateInfo, refInfo].map(x => Math.min(...x.methods[key].gasData)), BASE_TX_COST),
+ max: variation(...[updateInfo, refInfo].map(x => Math.max(...x.methods[key].gasData)), BASE_TX_COST),
+ avg: variation(...[updateInfo, refInfo].map(x => Math.round(average(...x.methods[key].gasData))), BASE_TX_COST),
+ }))
+ .sort((a, b) => `${a.contract}:${a.method}`.localeCompare(`${b.contract}:${b.method}`));
+
+ return []
+ .concat(deployments, methods)
+ .filter(row => !opts.hideEqual || row.min?.delta || row.max?.delta || row.avg?.delta);
+ }
+}
+
+// Display
+function center(text, length) {
+ return text.padStart((text.length + length) / 2).padEnd(length);
+}
+
+function plusSign(num) {
+ return num > 0 ? '+' : '';
+}
+
+function formatCellShell(cell) {
+ const format = chalk[cell?.delta > 0 ? 'red' : cell?.delta < 0 ? 'green' : 'reset'];
+ return [
+ format((!isFinite(cell?.value) ? '-' : cell.value.toString()).padStart(8)),
+ format((!isFinite(cell?.delta) ? '-' : plusSign(cell.delta) + cell.delta.toString()).padStart(8)),
+ format((!isFinite(cell?.prcnt) ? '-' : plusSign(cell.prcnt) + cell.prcnt.toFixed(2) + '%').padStart(8)),
+ ];
+}
+
+function formatCmpShell(rows) {
+ const contractLength = Math.max(8, ...rows.map(({ contract }) => contract.length));
+ const methodLength = Math.max(7, ...rows.map(({ method }) => method.length));
+
+ const COLS = [
+ { txt: '', length: 0 },
+ { txt: 'Contract', length: contractLength },
+ { txt: 'Method', length: methodLength },
+ { txt: 'Min', length: 30 },
+ { txt: 'Max', length: 30 },
+ { txt: 'Avg', length: 30 },
+ { txt: '', length: 0 },
+ ];
+ const HEADER = COLS.map(entry => chalk.bold(center(entry.txt, entry.length || 0)))
+ .join(' | ')
+ .trim();
+ const SEPARATOR = COLS.map(({ length }) => (length > 0 ? '-'.repeat(length + 2) : ''))
+ .join('|')
+ .trim();
+
+ return [
+ '',
+ HEADER,
+ ...rows.map(entry =>
+ [
+ '',
+ chalk.grey(entry.contract.padEnd(contractLength)),
+ entry.method.padEnd(methodLength),
+ ...formatCellShell(entry.min),
+ ...formatCellShell(entry.max),
+ ...formatCellShell(entry.avg),
+ '',
+ ]
+ .join(' | ')
+ .trim(),
+ ),
+ '',
+ ]
+ .join(`\n${SEPARATOR}\n`)
+ .trim();
+}
+
+function alignPattern(align) {
+ switch (align) {
+ case 'left':
+ case undefined:
+ return ':-';
+ case 'right':
+ return '-:';
+ case 'center':
+ return ':-:';
+ }
+}
+
+function trend(value) {
+ return value > 0 ? ':x:' : value < 0 ? ':heavy_check_mark:' : ':heavy_minus_sign:';
+}
+
+function formatCellMarkdown(cell) {
+ return [
+ !isFinite(cell?.value) ? '-' : cell.value.toString(),
+ !isFinite(cell?.delta) ? '-' : plusSign(cell.delta) + cell.delta.toString(),
+ !isFinite(cell?.prcnt) ? '-' : plusSign(cell.prcnt) + cell.prcnt.toFixed(2) + '% ' + trend(cell.delta),
+ ];
+}
+
+function formatCmpMarkdown(rows) {
+ const COLS = [
+ { txt: '' },
+ { txt: 'Contract', align: 'left' },
+ { txt: 'Method', align: 'left' },
+ { txt: 'Min', align: 'right' },
+ { txt: '(+/-)', align: 'right' },
+ { txt: '%', align: 'right' },
+ { txt: 'Max', align: 'right' },
+ { txt: '(+/-)', align: 'right' },
+ { txt: '%', align: 'right' },
+ { txt: 'Avg', align: 'right' },
+ { txt: '(+/-)', align: 'right' },
+ { txt: '%', align: 'right' },
+ { txt: '' },
+ ];
+ const HEADER = COLS.map(entry => entry.txt)
+ .join(' | ')
+ .trim();
+ const SEPARATOR = COLS.map(entry => (entry.txt ? alignPattern(entry.align) : ''))
+ .join('|')
+ .trim();
+
+ return [
+ '# Changes to gas costs',
+ '',
+ HEADER,
+ SEPARATOR,
+ rows
+ .map(entry =>
+ [
+ '',
+ entry.contract,
+ entry.method,
+ ...formatCellMarkdown(entry.min),
+ ...formatCellMarkdown(entry.max),
+ ...formatCellMarkdown(entry.avg),
+ '',
+ ]
+ .join(' | ')
+ .trim(),
+ )
+ .join('\n'),
+ '',
+ ]
+ .join('\n')
+ .trim();
+}
+
+// MAIN
+const report = Report.compare(Report.load(argv._[0]), Report.load(argv._[1]), argv);
+
+switch (argv.style) {
+ case 'markdown':
+ console.log(formatCmpMarkdown(report));
+ break;
+ case 'shell':
+ default:
+ console.log(formatCmpShell(report));
+ break;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/coverage.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/coverage.sh
new file mode 100644
index 000000000..a591069c4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/coverage.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+export COVERAGE=true
+export FOUNDRY_FUZZ_RUNS=10
+
+# Hardhat coverage
+hardhat coverage
+
+if [ "${CI:-"false"}" == "true" ]; then
+ # Foundry coverage
+ forge coverage --report lcov --ir-minimum
+ # Remove zero hits
+ sed -i '/,0/d' lcov.info
+fi
+
+# Reports are then uploaded to Codecov automatically by workflow, and merged.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/extract-layout.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/extract-layout.js
new file mode 100644
index 000000000..d0b99653a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/extract-layout.js
@@ -0,0 +1,38 @@
+const fs = require('fs');
+const { findAll, astDereferencer, srcDecoder } = require('solidity-ast/utils');
+const { extractStorageLayout } = require('@openzeppelin/upgrades-core/dist/storage/extract');
+
+const { _ } = require('yargs').argv;
+
+const skipPath = ['contracts/mocks/', 'contracts-exposed/'];
+const skipKind = ['interface', 'library'];
+
+function extractLayouts(path) {
+ const layout = {};
+ const { input, output } = JSON.parse(fs.readFileSync(path));
+
+ const decoder = srcDecoder(input, output);
+ const deref = astDereferencer(output);
+
+ for (const src in output.contracts) {
+ if (skipPath.some(prefix => src.startsWith(prefix))) {
+ continue;
+ }
+
+ for (const contractDef of findAll('ContractDefinition', output.sources[src].ast)) {
+ if (skipKind.includes(contractDef.contractKind)) {
+ continue;
+ }
+
+ layout[contractDef.name] = extractStorageLayout(
+ contractDef,
+ decoder,
+ deref,
+ output.contracts[src][contractDef.name].storageLayout,
+ );
+ }
+ }
+ return layout;
+}
+
+console.log(JSON.stringify(Object.assign(..._.map(extractLayouts))));
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/generation.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/generation.sh
new file mode 100644
index 000000000..00d609f94
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/generation.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+npm run generate
+git diff -R --exit-code
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/inheritance-ordering.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/inheritance-ordering.js
new file mode 100644
index 000000000..4ed2deec4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/inheritance-ordering.js
@@ -0,0 +1,55 @@
+#!/usr/bin/env node
+
+const path = require('path');
+const graphlib = require('graphlib');
+const match = require('micromatch');
+const { findAll } = require('solidity-ast/utils');
+const { _: artifacts } = require('yargs').argv;
+
+// files to skip
+const skipPatterns = ['contracts-exposed/**', 'contracts/mocks/**'];
+
+for (const artifact of artifacts) {
+ const { output: solcOutput } = require(path.resolve(__dirname, '../..', artifact));
+
+ const graph = new graphlib.Graph({ directed: true });
+ const names = {};
+ const linearized = [];
+
+ for (const source in solcOutput.contracts) {
+ if (match.any(source, skipPatterns)) continue;
+ for (const contractDef of findAll('ContractDefinition', solcOutput.sources[source].ast)) {
+ names[contractDef.id] = contractDef.name;
+ linearized.push(contractDef.linearizedBaseContracts);
+
+ contractDef.linearizedBaseContracts.forEach((c1, i, contracts) =>
+ contracts.slice(i + 1).forEach(c2 => {
+ graph.setEdge(c1, c2);
+ }),
+ );
+ }
+ }
+
+ /// graphlib.alg.findCycles will not find minimal cycles.
+ /// We are only interested int cycles of lengths 2 (needs proof)
+ graph.nodes().forEach((x, i, nodes) =>
+ nodes
+ .slice(i + 1)
+ .filter(y => graph.hasEdge(x, y) && graph.hasEdge(y, x))
+ .forEach(y => {
+ console.log(`Conflict between ${names[x]} and ${names[y]} detected in the following dependency chains:`);
+ linearized
+ .filter(chain => chain.includes(parseInt(x)) && chain.includes(parseInt(y)))
+ .forEach(chain => {
+ const comp = chain.indexOf(parseInt(x)) < chain.indexOf(parseInt(y)) ? '>' : '<';
+ console.log(`- ${names[x]} ${comp} ${names[y]} in ${names[chain.find(Boolean)]}`);
+ // console.log(`- ${names[x]} ${comp} ${names[y]}: ${chain.reverse().map(id => names[id]).join(', ')}`);
+ });
+ process.exitCode = 1;
+ }),
+ );
+}
+
+if (!process.exitCode) {
+ console.log('Contract ordering is consistent.');
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/pragma-consistency.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/pragma-consistency.js
new file mode 100644
index 000000000..f2f3c548f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/checks/pragma-consistency.js
@@ -0,0 +1,49 @@
+#!/usr/bin/env node
+
+const path = require('path');
+const semver = require('semver');
+const match = require('micromatch');
+const { findAll } = require('solidity-ast/utils');
+const { _: artifacts } = require('yargs').argv;
+
+// files to skip
+const skipPatterns = ['contracts-exposed/**', 'contracts/mocks/WithInit.sol'];
+
+for (const artifact of artifacts) {
+ const { output: solcOutput } = require(path.resolve(__dirname, '../..', artifact));
+
+ const pragma = {};
+
+ // Extract pragma directive for all files
+ for (const source in solcOutput.contracts) {
+ if (match.any(source, skipPatterns)) continue;
+ for (const { literals } of findAll('PragmaDirective', solcOutput.sources[source].ast)) {
+ // There should only be one.
+ const [first, ...rest] = literals;
+ if (first === 'solidity') pragma[source] = rest.join('');
+ }
+ }
+
+ // Compare the pragma directive of the file, to that of the files it imports
+ for (const source in solcOutput.contracts) {
+ if (match.any(source, skipPatterns)) continue;
+ // minimum version of the compiler that matches source's pragma
+ const minVersion = semver.minVersion(pragma[source]);
+ // loop over all imports in source
+ for (const { absolutePath } of findAll('ImportDirective', solcOutput.sources[source].ast)) {
+ // So files that only import without declaring anything cause issues, because they don't shop in in "pragma"
+ if (!pragma[absolutePath]) continue;
+ // Check that the minVersion for source satisfies the requirements of the imported files
+ if (!semver.satisfies(minVersion, pragma[absolutePath])) {
+ console.log(
+ `- ${source} uses ${pragma[source]} but depends on ${absolutePath} that requires ${pragma[absolutePath]}`,
+ );
+ process.exitCode = 1;
+ }
+ }
+ }
+}
+
+if (!process.exitCode) {
+ console.log('Pragma directives are consistent.');
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/gen-nav.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/gen-nav.js
new file mode 100644
index 000000000..de3d0daba
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/gen-nav.js
@@ -0,0 +1,41 @@
+#!/usr/bin/env node
+
+const path = require('path');
+const glob = require('glob');
+const startCase = require('lodash.startcase');
+
+const baseDir = process.argv[2];
+
+const files = glob.sync(baseDir + '/**/*.adoc').map(f => path.relative(baseDir, f));
+
+console.log('.API');
+
+function getPageTitle(directory) {
+ switch (directory) {
+ case 'metatx':
+ return 'Meta Transactions';
+ case 'common':
+ return 'Common (Tokens)';
+ default:
+ return startCase(directory);
+ }
+}
+
+const links = files.map(file => {
+ const doc = file.replace(baseDir, '');
+ const title = path.parse(file).name;
+
+ return {
+ xref: `* xref:${doc}[${getPageTitle(title)}]`,
+ title,
+ };
+});
+
+// Case-insensitive sort based on titles (so 'token/ERC20' gets sorted as 'erc20')
+const sortedLinks = links.sort(function (a, b) {
+ return a.title.toLowerCase().localeCompare(b.title.toLowerCase(), undefined, { numeric: true });
+});
+
+for (const link of sortedLinks) {
+ console.log(link.xref);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/format-lines.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/format-lines.js
new file mode 100644
index 000000000..fa3d6b120
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/format-lines.js
@@ -0,0 +1,16 @@
+function formatLines(...lines) {
+ return [...indentEach(0, lines)].join('\n') + '\n';
+}
+
+function* indentEach(indent, lines) {
+ for (const line of lines) {
+ if (Array.isArray(line)) {
+ yield* indentEach(indent + 1, line);
+ } else {
+ const padding = ' '.repeat(indent);
+ yield* line.split('\n').map(subline => (subline === '' ? '' : padding + subline));
+ }
+ }
+}
+
+module.exports = formatLines;
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/helpers/sanitize.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/helpers/sanitize.js
new file mode 100644
index 000000000..e680ec1bf
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/helpers/sanitize.js
@@ -0,0 +1,5 @@
+module.exports = {
+ address: expr => `and(${expr}, shr(96, not(0)))`,
+ bool: expr => `iszero(iszero(${expr}))`,
+ bytes: (expr, size) => `and(${expr}, shl(${256 - 8 * size}, not(0)))`,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/run.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/run.js
new file mode 100644
index 000000000..6779c93f4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/run.js
@@ -0,0 +1,58 @@
+#!/usr/bin/env node
+
+// const cp = require('child_process');
+const fs = require('fs');
+const path = require('path');
+const format = require('./format-lines');
+
+function getVersion(path) {
+ try {
+ return fs.readFileSync(path, 'utf8').match(/\/\/ OpenZeppelin Contracts \(last updated v[^)]+\)/)[0];
+ } catch {
+ return null;
+ }
+}
+
+function generateFromTemplate(file, template, outputPrefix = '') {
+ const script = path.relative(path.join(__dirname, '../..'), __filename);
+ const input = path.join(path.dirname(script), template);
+ const output = path.join(outputPrefix, file);
+ const version = getVersion(output);
+ const content = format(
+ '// SPDX-License-Identifier: MIT',
+ ...(version ? [version + ` (${file})`] : []),
+ `// This file was procedurally generated from ${input}.`,
+ '',
+ require(template).trimEnd(),
+ );
+
+ fs.writeFileSync(output, content);
+ // cp.execFileSync('prettier', ['--write', output]);
+}
+
+// Contracts
+for (const [file, template] of Object.entries({
+ 'utils/cryptography/MerkleProof.sol': './templates/MerkleProof.js',
+ 'utils/math/SafeCast.sol': './templates/SafeCast.js',
+ 'utils/structs/Checkpoints.sol': './templates/Checkpoints.js',
+ 'utils/structs/EnumerableSet.sol': './templates/EnumerableSet.js',
+ 'utils/structs/EnumerableMap.sol': './templates/EnumerableMap.js',
+ 'utils/SlotDerivation.sol': './templates/SlotDerivation.js',
+ 'utils/StorageSlot.sol': './templates/StorageSlot.js',
+ 'utils/TransientSlot.sol': './templates/TransientSlot.js',
+ 'utils/Arrays.sol': './templates/Arrays.js',
+ 'utils/Packing.sol': './templates/Packing.js',
+ 'mocks/StorageSlotMock.sol': './templates/StorageSlotMock.js',
+ 'mocks/TransientSlotMock.sol': './templates/TransientSlotMock.js',
+})) {
+ generateFromTemplate(file, template, './contracts/');
+}
+
+// Tests
+for (const [file, template] of Object.entries({
+ 'utils/structs/Checkpoints.t.sol': './templates/Checkpoints.t.js',
+ 'utils/Packing.t.sol': './templates/Packing.t.js',
+ 'utils/SlotDerivation.t.sol': './templates/SlotDerivation.t.js',
+})) {
+ generateFromTemplate(file, template, './test/');
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.js
new file mode 100644
index 000000000..0d3676a72
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.js
@@ -0,0 +1,384 @@
+const format = require('../format-lines');
+const { capitalize } = require('../../helpers');
+const { TYPES } = require('./Arrays.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Comparators} from "./Comparators.sol";
+import {SlotDerivation} from "./SlotDerivation.sol";
+import {StorageSlot} from "./StorageSlot.sol";
+import {Math} from "./math/Math.sol";
+
+/**
+ * @dev Collection of functions related to array types.
+ */
+`;
+
+const sort = type => `\
+/**
+ * @dev Sort an array of ${type} (in memory) following the provided comparator function.
+ *
+ * This function does the sorting "in place", meaning that it overrides the input. The object is returned for
+ * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
+ *
+ * NOTE: this function's cost is \`O(n · log(n))\` in average and \`O(n²)\` in the worst case, with n the length of the
+ * array. Using it in view functions that are executed through \`eth_call\` is safe, but one should be very careful
+ * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
+ * consume more gas than is available in a block, leading to potential DoS.
+ *
+ * IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
+ */
+function sort(
+ ${type}[] memory array,
+ function(${type}, ${type}) pure returns (bool) comp
+) internal pure returns (${type}[] memory) {
+ ${
+ type === 'uint256'
+ ? '_quickSort(_begin(array), _end(array), comp);'
+ : 'sort(_castToUint256Array(array), _castToUint256Comp(comp));'
+ }
+ return array;
+}
+
+/**
+ * @dev Variant of {sort} that sorts an array of ${type} in increasing order.
+ */
+function sort(${type}[] memory array) internal pure returns (${type}[] memory) {
+ ${type === 'uint256' ? 'sort(array, Comparators.lt);' : 'sort(_castToUint256Array(array), Comparators.lt);'}
+ return array;
+}
+`;
+
+const quickSort = `\
+/**
+ * @dev Performs a quick sort of a segment of memory. The segment sorted starts at \`begin\` (inclusive), and stops
+ * at end (exclusive). Sorting follows the \`comp\` comparator.
+ *
+ * Invariant: \`begin <= end\`. This is the case when initially called by {sort} and is preserved in subcalls.
+ *
+ * IMPORTANT: Memory locations between \`begin\` and \`end\` are not validated/zeroed. This function should
+ * be used only if the limits are within a memory array.
+ */
+function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {
+ unchecked {
+ if (end - begin < 0x40) return;
+
+ // Use first element as pivot
+ uint256 pivot = _mload(begin);
+ // Position where the pivot should be at the end of the loop
+ uint256 pos = begin;
+
+ for (uint256 it = begin + 0x20; it < end; it += 0x20) {
+ if (comp(_mload(it), pivot)) {
+ // If the value stored at the iterator's position comes before the pivot, we increment the
+ // position of the pivot and move the value there.
+ pos += 0x20;
+ _swap(pos, it);
+ }
+ }
+
+ _swap(begin, pos); // Swap pivot into place
+ _quickSort(begin, pos, comp); // Sort the left side of the pivot
+ _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
+ }
+}
+
+/**
+ * @dev Pointer to the memory location of the first element of \`array\`.
+ */
+function _begin(uint256[] memory array) private pure returns (uint256 ptr) {
+ assembly ("memory-safe") {
+ ptr := add(array, 0x20)
+ }
+}
+
+/**
+ * @dev Pointer to the memory location of the first memory word (32bytes) after \`array\`. This is the memory word
+ * that comes just after the last element of the array.
+ */
+function _end(uint256[] memory array) private pure returns (uint256 ptr) {
+ unchecked {
+ return _begin(array) + array.length * 0x20;
+ }
+}
+
+/**
+ * @dev Load memory word (as a uint256) at location \`ptr\`.
+ */
+function _mload(uint256 ptr) private pure returns (uint256 value) {
+ assembly {
+ value := mload(ptr)
+ }
+}
+
+/**
+ * @dev Swaps the elements memory location \`ptr1\` and \`ptr2\`.
+ */
+function _swap(uint256 ptr1, uint256 ptr2) private pure {
+ assembly {
+ let value1 := mload(ptr1)
+ let value2 := mload(ptr2)
+ mstore(ptr1, value2)
+ mstore(ptr2, value1)
+ }
+}
+`;
+
+const castArray = type => `\
+/// @dev Helper: low level cast ${type} memory array to uint256 memory array
+function _castToUint256Array(${type}[] memory input) private pure returns (uint256[] memory output) {
+ assembly {
+ output := input
+ }
+}
+`;
+
+const castComparator = type => `\
+/// @dev Helper: low level cast ${type} comp function to uint256 comp function
+function _castToUint256Comp(
+ function(${type}, ${type}) pure returns (bool) input
+) private pure returns (function(uint256, uint256) pure returns (bool) output) {
+ assembly {
+ output := input
+ }
+}
+`;
+
+const search = `\
+/**
+ * @dev Searches a sorted \`array\` and returns the first index that contains
+ * a value greater or equal to \`element\`. If no such index exists (i.e. all
+ * values in the array are strictly less than \`element\`), the array length is
+ * returned. Time complexity O(log n).
+ *
+ * NOTE: The \`array\` is expected to be sorted in ascending order, and to
+ * contain no repeated elements.
+ *
+ * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
+ * support for repeated elements in the array. The {lowerBound} function should
+ * be used instead.
+ */
+function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
+ uint256 low = 0;
+ uint256 high = array.length;
+
+ if (high == 0) {
+ return 0;
+ }
+
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+
+ // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
+ // because Math.average rounds towards zero (it does integer division with truncation).
+ if (unsafeAccess(array, mid).value > element) {
+ high = mid;
+ } else {
+ low = mid + 1;
+ }
+ }
+
+ // At this point \`low\` is the exclusive upper bound. We will return the inclusive upper bound.
+ if (low > 0 && unsafeAccess(array, low - 1).value == element) {
+ return low - 1;
+ } else {
+ return low;
+ }
+}
+
+/**
+ * @dev Searches an \`array\` sorted in ascending order and returns the first
+ * index that contains a value greater or equal than \`element\`. If no such index
+ * exists (i.e. all values in the array are strictly less than \`element\`), the array
+ * length is returned. Time complexity O(log n).
+ *
+ * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
+ */
+function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
+ uint256 low = 0;
+ uint256 high = array.length;
+
+ if (high == 0) {
+ return 0;
+ }
+
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+
+ // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
+ // because Math.average rounds towards zero (it does integer division with truncation).
+ if (unsafeAccess(array, mid).value < element) {
+ // this cannot overflow because mid < high
+ unchecked {
+ low = mid + 1;
+ }
+ } else {
+ high = mid;
+ }
+ }
+
+ return low;
+}
+
+/**
+ * @dev Searches an \`array\` sorted in ascending order and returns the first
+ * index that contains a value strictly greater than \`element\`. If no such index
+ * exists (i.e. all values in the array are strictly less than \`element\`), the array
+ * length is returned. Time complexity O(log n).
+ *
+ * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
+ */
+function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
+ uint256 low = 0;
+ uint256 high = array.length;
+
+ if (high == 0) {
+ return 0;
+ }
+
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+
+ // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
+ // because Math.average rounds towards zero (it does integer division with truncation).
+ if (unsafeAccess(array, mid).value > element) {
+ high = mid;
+ } else {
+ // this cannot overflow because mid < high
+ unchecked {
+ low = mid + 1;
+ }
+ }
+ }
+
+ return low;
+}
+
+/**
+ * @dev Same as {lowerBound}, but with an array in memory.
+ */
+function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
+ uint256 low = 0;
+ uint256 high = array.length;
+
+ if (high == 0) {
+ return 0;
+ }
+
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+
+ // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
+ // because Math.average rounds towards zero (it does integer division with truncation).
+ if (unsafeMemoryAccess(array, mid) < element) {
+ // this cannot overflow because mid < high
+ unchecked {
+ low = mid + 1;
+ }
+ } else {
+ high = mid;
+ }
+ }
+
+ return low;
+}
+
+/**
+ * @dev Same as {upperBound}, but with an array in memory.
+ */
+function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
+ uint256 low = 0;
+ uint256 high = array.length;
+
+ if (high == 0) {
+ return 0;
+ }
+
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+
+ // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
+ // because Math.average rounds towards zero (it does integer division with truncation).
+ if (unsafeMemoryAccess(array, mid) > element) {
+ high = mid;
+ } else {
+ // this cannot overflow because mid < high
+ unchecked {
+ low = mid + 1;
+ }
+ }
+ }
+
+ return low;
+}
+`;
+
+const unsafeAccessStorage = type => `\
+/**
+ * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
+ *
+ * WARNING: Only use if you are certain \`pos\` is lower than the array length.
+ */
+function unsafeAccess(${type}[] storage arr, uint256 pos) internal pure returns (StorageSlot.${capitalize(
+ type,
+)}Slot storage) {
+ bytes32 slot;
+ assembly ("memory-safe") {
+ slot := arr.slot
+ }
+ return slot.deriveArray().offset(pos).get${capitalize(type)}Slot();
+}
+`;
+
+const unsafeAccessMemory = type => `\
+/**
+ * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
+ *
+ * WARNING: Only use if you are certain \`pos\` is lower than the array length.
+ */
+function unsafeMemoryAccess(${type}[] memory arr, uint256 pos) internal pure returns (${type} res) {
+ assembly {
+ res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
+ }
+}
+`;
+
+const unsafeSetLength = type => `\
+/**
+ * @dev Helper to set the length of an dynamic array. Directly writing to \`.length\` is forbidden.
+ *
+ * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
+ */
+function unsafeSetLength(${type}[] storage array, uint256 len) internal {
+ assembly ("memory-safe") {
+ sstore(array.slot, len)
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library Arrays {',
+ format(
+ [].concat(
+ 'using SlotDerivation for bytes32;',
+ 'using StorageSlot for bytes32;',
+ '',
+ // sorting, comparator, helpers and internal
+ sort('uint256'),
+ TYPES.filter(type => type !== 'uint256').map(sort),
+ quickSort,
+ TYPES.filter(type => type !== 'uint256').map(castArray),
+ TYPES.filter(type => type !== 'uint256').map(castComparator),
+ // lookup
+ search,
+ // unsafe (direct) storage and memory access
+ TYPES.map(unsafeAccessStorage),
+ TYPES.map(unsafeAccessMemory),
+ TYPES.map(unsafeSetLength),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.opts.js
new file mode 100644
index 000000000..67f329972
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Arrays.opts.js
@@ -0,0 +1,3 @@
+const TYPES = ['address', 'bytes32', 'uint256'];
+
+module.exports = { TYPES };
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.js
new file mode 100644
index 000000000..7ec4a7253
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.js
@@ -0,0 +1,242 @@
+const format = require('../format-lines');
+const { OPTS } = require('./Checkpoints.opts');
+
+// TEMPLATE
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Math} from "../math/Math.sol";
+
+/**
+ * @dev This library defines the \`Trace*\` struct, for checkpointing values as they change at different points in
+ * time, and later looking up past values by block number. See {Votes} as an example.
+ *
+ * To create a history of checkpoints define a variable type \`Checkpoints.Trace*\` in your contract, and store a new
+ * checkpoint for the current transaction block using the {push} function.
+ */
+`;
+
+const errors = `\
+/**
+ * @dev A value was attempted to be inserted on a past checkpoint.
+ */
+error CheckpointUnorderedInsertion();
+`;
+
+const template = opts => `\
+struct ${opts.historyTypeName} {
+ ${opts.checkpointTypeName}[] ${opts.checkpointFieldName};
+}
+
+struct ${opts.checkpointTypeName} {
+ ${opts.keyTypeName} ${opts.keyFieldName};
+ ${opts.valueTypeName} ${opts.valueFieldName};
+}
+
+/**
+ * @dev Pushes a (\`key\`, \`value\`) pair into a ${opts.historyTypeName} so that it is stored as the checkpoint.
+ *
+ * Returns previous value and new value.
+ *
+ * IMPORTANT: Never accept \`key\` as a user input, since an arbitrary \`type(${opts.keyTypeName}).max\` key set will disable the
+ * library.
+ */
+function push(
+ ${opts.historyTypeName} storage self,
+ ${opts.keyTypeName} key,
+ ${opts.valueTypeName} value
+) internal returns (${opts.valueTypeName} oldValue, ${opts.valueTypeName} newValue) {
+ return _insert(self.${opts.checkpointFieldName}, key, value);
+}
+
+/**
+ * @dev Returns the value in the first (oldest) checkpoint with key greater or equal than the search key, or zero if
+ * there is none.
+ */
+function lowerLookup(${opts.historyTypeName} storage self, ${opts.keyTypeName} key) internal view returns (${opts.valueTypeName}) {
+ uint256 len = self.${opts.checkpointFieldName}.length;
+ uint256 pos = _lowerBinaryLookup(self.${opts.checkpointFieldName}, key, 0, len);
+ return pos == len ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos).${opts.valueFieldName};
+}
+
+/**
+ * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
+ * if there is none.
+ */
+function upperLookup(${opts.historyTypeName} storage self, ${opts.keyTypeName} key) internal view returns (${opts.valueTypeName}) {
+ uint256 len = self.${opts.checkpointFieldName}.length;
+ uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, 0, len);
+ return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
+}
+
+/**
+ * @dev Returns the value in the last (most recent) checkpoint with key lower or equal than the search key, or zero
+ * if there is none.
+ *
+ * NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high
+ * keys).
+ */
+function upperLookupRecent(${opts.historyTypeName} storage self, ${opts.keyTypeName} key) internal view returns (${opts.valueTypeName}) {
+ uint256 len = self.${opts.checkpointFieldName}.length;
+
+ uint256 low = 0;
+ uint256 high = len;
+
+ if (len > 5) {
+ uint256 mid = len - Math.sqrt(len);
+ if (key < _unsafeAccess(self.${opts.checkpointFieldName}, mid)._key) {
+ high = mid;
+ } else {
+ low = mid + 1;
+ }
+ }
+
+ uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, low, high);
+
+ return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
+}
+
+/**
+ * @dev Returns the value in the most recent checkpoint, or zero if there are no checkpoints.
+ */
+function latest(${opts.historyTypeName} storage self) internal view returns (${opts.valueTypeName}) {
+ uint256 pos = self.${opts.checkpointFieldName}.length;
+ return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
+}
+
+/**
+ * @dev Returns whether there is a checkpoint in the structure (i.e. it is not empty), and if so the key and value
+ * in the most recent checkpoint.
+ */
+function latestCheckpoint(${opts.historyTypeName} storage self) internal view returns (bool exists, ${opts.keyTypeName} ${opts.keyFieldName}, ${opts.valueTypeName} ${opts.valueFieldName}) {
+ uint256 pos = self.${opts.checkpointFieldName}.length;
+ if (pos == 0) {
+ return (false, 0, 0);
+ } else {
+ ${opts.checkpointTypeName} storage ckpt = _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1);
+ return (true, ckpt.${opts.keyFieldName}, ckpt.${opts.valueFieldName});
+ }
+}
+
+/**
+ * @dev Returns the number of checkpoint.
+ */
+function length(${opts.historyTypeName} storage self) internal view returns (uint256) {
+ return self.${opts.checkpointFieldName}.length;
+}
+
+/**
+ * @dev Returns checkpoint at given position.
+ */
+function at(${opts.historyTypeName} storage self, uint32 pos) internal view returns (${opts.checkpointTypeName} memory) {
+ return self.${opts.checkpointFieldName}[pos];
+}
+
+/**
+ * @dev Pushes a (\`key\`, \`value\`) pair into an ordered list of checkpoints, either by inserting a new checkpoint,
+ * or by updating the last one.
+ */
+function _insert(
+ ${opts.checkpointTypeName}[] storage self,
+ ${opts.keyTypeName} key,
+ ${opts.valueTypeName} value
+) private returns (${opts.valueTypeName} oldValue, ${opts.valueTypeName} newValue) {
+ uint256 pos = self.length;
+
+ if (pos > 0) {
+ ${opts.checkpointTypeName} storage last = _unsafeAccess(self, pos - 1);
+ ${opts.keyTypeName} lastKey = last.${opts.keyFieldName};
+ ${opts.valueTypeName} lastValue = last.${opts.valueFieldName};
+
+ // Checkpoint keys must be non-decreasing.
+ if (lastKey > key) {
+ revert CheckpointUnorderedInsertion();
+ }
+
+ // Update or push new checkpoint
+ if (lastKey == key) {
+ last.${opts.valueFieldName} = value;
+ } else {
+ self.push(${opts.checkpointTypeName}({${opts.keyFieldName}: key, ${opts.valueFieldName}: value}));
+ }
+ return (lastValue, value);
+ } else {
+ self.push(${opts.checkpointTypeName}({${opts.keyFieldName}: key, ${opts.valueFieldName}: value}));
+ return (0, value);
+ }
+}
+
+/**
+ * @dev Return the index of the first (oldest) checkpoint with key strictly bigger than the search key, or \`high\`
+ * if there is none. \`low\` and \`high\` define a section where to do the search, with inclusive \`low\` and exclusive
+ * \`high\`.
+ *
+ * WARNING: \`high\` should not be greater than the array's length.
+ */
+function _upperBinaryLookup(
+ ${opts.checkpointTypeName}[] storage self,
+ ${opts.keyTypeName} key,
+ uint256 low,
+ uint256 high
+) private view returns (uint256) {
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+ if (_unsafeAccess(self, mid).${opts.keyFieldName} > key) {
+ high = mid;
+ } else {
+ low = mid + 1;
+ }
+ }
+ return high;
+}
+
+/**
+ * @dev Return the index of the first (oldest) checkpoint with key greater or equal than the search key, or \`high\`
+ * if there is none. \`low\` and \`high\` define a section where to do the search, with inclusive \`low\` and exclusive
+ * \`high\`.
+ *
+ * WARNING: \`high\` should not be greater than the array's length.
+ */
+function _lowerBinaryLookup(
+ ${opts.checkpointTypeName}[] storage self,
+ ${opts.keyTypeName} key,
+ uint256 low,
+ uint256 high
+) private view returns (uint256) {
+ while (low < high) {
+ uint256 mid = Math.average(low, high);
+ if (_unsafeAccess(self, mid).${opts.keyFieldName} < key) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+}
+
+/**
+ * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
+ */
+function _unsafeAccess(
+ ${opts.checkpointTypeName}[] storage self,
+ uint256 pos
+) private pure returns (${opts.checkpointTypeName} storage result) {
+ assembly {
+ mstore(0, self.slot)
+ result.slot := add(keccak256(0, 0x20), pos)
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library Checkpoints {',
+ format(
+ [].concat(
+ errors,
+ OPTS.map(opts => template(opts)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.opts.js
new file mode 100644
index 000000000..08b7b910b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.opts.js
@@ -0,0 +1,17 @@
+// OPTIONS
+const VALUE_SIZES = [224, 208, 160];
+
+const defaultOpts = size => ({
+ historyTypeName: `Trace${size}`,
+ checkpointTypeName: `Checkpoint${size}`,
+ checkpointFieldName: '_checkpoints',
+ keyTypeName: `uint${256 - size}`,
+ keyFieldName: '_key',
+ valueTypeName: `uint${size}`,
+ valueFieldName: '_value',
+});
+
+module.exports = {
+ VALUE_SIZES,
+ OPTS: VALUE_SIZES.map(size => defaultOpts(size)),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.t.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.t.js
new file mode 100644
index 000000000..edd2e9f98
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Checkpoints.t.js
@@ -0,0 +1,137 @@
+const format = require('../format-lines');
+const { capitalize } = require('../../helpers');
+const { OPTS } = require('./Checkpoints.opts.js');
+
+// TEMPLATE
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
+import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
+`;
+
+const template = opts => `\
+using Checkpoints for Checkpoints.${opts.historyTypeName};
+
+// Maximum gap between keys used during the fuzzing tests: the \`_prepareKeys\` function with make sure that
+// key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range.
+uint8 internal constant _KEY_MAX_GAP = 64;
+
+Checkpoints.${opts.historyTypeName} internal _ckpts;
+
+// helpers
+function _bound${capitalize(opts.keyTypeName)}(${opts.keyTypeName} x, ${opts.keyTypeName} min, ${
+ opts.keyTypeName
+} max) internal pure returns (${opts.keyTypeName}) {
+ return SafeCast.to${capitalize(opts.keyTypeName)}(bound(uint256(x), uint256(min), uint256(max)));
+}
+
+function _prepareKeys(${opts.keyTypeName}[] memory keys, ${opts.keyTypeName} maxSpread) internal pure {
+ ${opts.keyTypeName} lastKey = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ ${opts.keyTypeName} key = _bound${capitalize(opts.keyTypeName)}(keys[i], lastKey, lastKey + maxSpread);
+ keys[i] = key;
+ lastKey = key;
+ }
+}
+
+function _assertLatestCheckpoint(bool exist, ${opts.keyTypeName} key, ${opts.valueTypeName} value) internal {
+ (bool _exist, ${opts.keyTypeName} _key, ${opts.valueTypeName} _value) = _ckpts.latestCheckpoint();
+ assertEq(_exist, exist);
+ assertEq(_key, key);
+ assertEq(_value, value);
+}
+
+// tests
+function testPush(${opts.keyTypeName}[] memory keys, ${opts.valueTypeName}[] memory values, ${
+ opts.keyTypeName
+} pastKey) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ // initial state
+ assertEq(_ckpts.length(), 0);
+ assertEq(_ckpts.latest(), 0);
+ _assertLatestCheckpoint(false, 0, 0);
+
+ uint256 duplicates = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ ${opts.keyTypeName} key = keys[i];
+ ${opts.valueTypeName} value = values[i % values.length];
+ if (i > 0 && key == keys[i - 1]) ++duplicates;
+
+ // push
+ _ckpts.push(key, value);
+
+ // check length & latest
+ assertEq(_ckpts.length(), i + 1 - duplicates);
+ assertEq(_ckpts.latest(), value);
+ _assertLatestCheckpoint(true, key, value);
+ }
+
+ if (keys.length > 0) {
+ ${opts.keyTypeName} lastKey = keys[keys.length - 1];
+ if (lastKey > 0) {
+ pastKey = _bound${capitalize(opts.keyTypeName)}(pastKey, 0, lastKey - 1);
+
+ vm.expectRevert();
+ this.push(pastKey, values[keys.length % values.length]);
+ }
+ }
+}
+
+// used to test reverts
+function push(${opts.keyTypeName} key, ${opts.valueTypeName} value) external {
+ _ckpts.push(key, value);
+}
+
+function testLookup(${opts.keyTypeName}[] memory keys, ${opts.valueTypeName}[] memory values, ${
+ opts.keyTypeName
+} lookup) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ ${opts.keyTypeName} lastKey = keys.length == 0 ? 0 : keys[keys.length - 1];
+ lookup = _bound${capitalize(opts.keyTypeName)}(lookup, 0, lastKey + _KEY_MAX_GAP);
+
+ ${opts.valueTypeName} upper = 0;
+ ${opts.valueTypeName} lower = 0;
+ ${opts.keyTypeName} lowerKey = type(${opts.keyTypeName}).max;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ ${opts.keyTypeName} key = keys[i];
+ ${opts.valueTypeName} value = values[i % values.length];
+
+ // push
+ _ckpts.push(key, value);
+
+ // track expected result of lookups
+ if (key <= lookup) {
+ upper = value;
+ }
+ // find the first key that is not smaller than the lookup key
+ if (key >= lookup && (i == 0 || keys[i - 1] < lookup)) {
+ lowerKey = key;
+ }
+ if (key == lowerKey) {
+ lower = value;
+ }
+ }
+
+ // check lookup
+ assertEq(_ckpts.lowerLookup(lookup), lower);
+ assertEq(_ckpts.upperLookup(lookup), upper);
+ assertEq(_ckpts.upperLookupRecent(lookup), upper);
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header,
+ ...OPTS.flatMap(opts => [
+ `contract Checkpoints${opts.historyTypeName}Test is Test {`,
+ [template(opts).trimEnd()],
+ '}',
+ '',
+ ]),
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.js
new file mode 100644
index 000000000..c9cad6c1b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.js
@@ -0,0 +1,272 @@
+const format = require('../format-lines');
+const { fromBytes32, toBytes32 } = require('./conversion');
+const { TYPES } = require('./EnumerableMap.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+import {EnumerableSet} from "./EnumerableSet.sol";
+
+/**
+ * @dev Library for managing an enumerable variant of Solidity's
+ * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[\`mapping\`]
+ * type.
+ *
+ * Maps have the following properties:
+ *
+ * - Entries are added, removed, and checked for existence in constant time
+ * (O(1)).
+ * - Entries are enumerated in O(n). No guarantees are made on the ordering.
+ *
+ * \`\`\`solidity
+ * contract Example {
+ * // Add the library methods
+ * using EnumerableMap for EnumerableMap.UintToAddressMap;
+ *
+ * // Declare a set state variable
+ * EnumerableMap.UintToAddressMap private myMap;
+ * }
+ * \`\`\`
+ *
+ * The following map types are supported:
+ *
+ * - \`uint256 -> address\` (\`UintToAddressMap\`) since v3.0.0
+ * - \`address -> uint256\` (\`AddressToUintMap\`) since v4.6.0
+ * - \`bytes32 -> bytes32\` (\`Bytes32ToBytes32Map\`) since v4.6.0
+ * - \`uint256 -> uint256\` (\`UintToUintMap\`) since v4.7.0
+ * - \`bytes32 -> uint256\` (\`Bytes32ToUintMap\`) since v4.7.0
+ * - \`uint256 -> bytes32\` (\`UintToBytes32Map\`) since v5.1.0
+ * - \`address -> address\` (\`AddressToAddressMap\`) since v5.1.0
+ * - \`address -> bytes32\` (\`AddressToBytes32Map\`) since v5.1.0
+ * - \`bytes32 -> address\` (\`Bytes32ToAddressMap\`) since v5.1.0
+ *
+ * [WARNING]
+ * ====
+ * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
+ * unusable.
+ * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
+ *
+ * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
+ * array of EnumerableMap.
+ * ====
+ */
+`;
+
+const defaultMap = `\
+// To implement this library for multiple types with as little code repetition as possible, we write it in
+// terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions,
+// and user-facing implementations such as \`UintToAddressMap\` are just wrappers around the underlying Map.
+// This means that we can only create new EnumerableMaps for types that fit in bytes32.
+
+/**
+ * @dev Query for a nonexistent map key.
+ */
+error EnumerableMapNonexistentKey(bytes32 key);
+
+struct Bytes32ToBytes32Map {
+ // Storage of keys
+ EnumerableSet.Bytes32Set _keys;
+ mapping(bytes32 key => bytes32) _values;
+}
+
+/**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
+ map._values[key] = value;
+ return map._keys.add(key);
+}
+
+/**
+ * @dev Removes a key-value pair from a map. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
+ delete map._values[key];
+ return map._keys.remove(key);
+}
+
+/**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
+ return map._keys.contains(key);
+}
+
+/**
+ * @dev Returns the number of key-value pairs in the map. O(1).
+ */
+function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
+ return map._keys.length();
+}
+
+/**
+ * @dev Returns the key-value pair stored at position \`index\` in the map. O(1).
+ *
+ * Note that there are no guarantees on the ordering of entries inside the
+ * array, and it may change when more entries are added or removed.
+ *
+ * Requirements:
+ *
+ * - \`index\` must be strictly less than {length}.
+ */
+function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) {
+ bytes32 atKey = map._keys.at(index);
+ return (atKey, map._values[atKey]);
+}
+
+/**
+ * @dev Tries to returns the value associated with \`key\`. O(1).
+ * Does not revert if \`key\` is not in the map.
+ */
+function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool exists, bytes32 value) {
+ bytes32 val = map._values[key];
+ if (val == bytes32(0)) {
+ return (contains(map, key), bytes32(0));
+ } else {
+ return (true, val);
+ }
+}
+
+/**
+ * @dev Returns the value associated with \`key\`. O(1).
+ *
+ * Requirements:
+ *
+ * - \`key\` must be in the map.
+ */
+function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
+ bytes32 value = map._values[key];
+ if (value == 0 && !contains(map, key)) {
+ revert EnumerableMapNonexistentKey(key);
+ }
+ return value;
+}
+
+/**
+ * @dev Return the an array containing all the keys
+ *
+ * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
+ * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
+ * this function has an unbounded cost, and using it as part of a state-changing function may render the function
+ * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
+ */
+function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
+ return map._keys.values();
+}
+`;
+
+const customMap = ({ name, keyType, valueType }) => `\
+// ${name}
+
+struct ${name} {
+ Bytes32ToBytes32Map _inner;
+}
+
+/**
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
+ * key. O(1).
+ *
+ * Returns true if the key was added to the map, that is if it was not
+ * already present.
+ */
+function set(${name} storage map, ${keyType} key, ${valueType} value) internal returns (bool) {
+ return set(map._inner, ${toBytes32(keyType, 'key')}, ${toBytes32(valueType, 'value')});
+}
+
+/**
+ * @dev Removes a value from a map. O(1).
+ *
+ * Returns true if the key was removed from the map, that is if it was present.
+ */
+function remove(${name} storage map, ${keyType} key) internal returns (bool) {
+ return remove(map._inner, ${toBytes32(keyType, 'key')});
+}
+
+/**
+ * @dev Returns true if the key is in the map. O(1).
+ */
+function contains(${name} storage map, ${keyType} key) internal view returns (bool) {
+ return contains(map._inner, ${toBytes32(keyType, 'key')});
+}
+
+/**
+ * @dev Returns the number of elements in the map. O(1).
+ */
+function length(${name} storage map) internal view returns (uint256) {
+ return length(map._inner);
+}
+
+/**
+ * @dev Returns the element stored at position \`index\` in the map. O(1).
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - \`index\` must be strictly less than {length}.
+ */
+function at(${name} storage map, uint256 index) internal view returns (${keyType} key, ${valueType} value) {
+ (bytes32 atKey, bytes32 val) = at(map._inner, index);
+ return (${fromBytes32(keyType, 'atKey')}, ${fromBytes32(valueType, 'val')});
+}
+
+/**
+ * @dev Tries to returns the value associated with \`key\`. O(1).
+ * Does not revert if \`key\` is not in the map.
+ */
+function tryGet(${name} storage map, ${keyType} key) internal view returns (bool exists, ${valueType} value) {
+ (bool success, bytes32 val) = tryGet(map._inner, ${toBytes32(keyType, 'key')});
+ return (success, ${fromBytes32(valueType, 'val')});
+}
+
+/**
+ * @dev Returns the value associated with \`key\`. O(1).
+ *
+ * Requirements:
+ *
+ * - \`key\` must be in the map.
+ */
+function get(${name} storage map, ${keyType} key) internal view returns (${valueType}) {
+ return ${fromBytes32(valueType, `get(map._inner, ${toBytes32(keyType, 'key')})`)};
+}
+
+/**
+ * @dev Return the an array containing all the keys
+ *
+ * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
+ * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
+ * this function has an unbounded cost, and using it as part of a state-changing function may render the function
+ * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
+ */
+function keys(${name} storage map) internal view returns (${keyType}[] memory) {
+ bytes32[] memory store = keys(map._inner);
+ ${keyType}[] memory result;
+
+ assembly ("memory-safe") {
+ result := store
+ }
+
+ return result;
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library EnumerableMap {',
+ format(
+ [].concat(
+ 'using EnumerableSet for EnumerableSet.Bytes32Set;',
+ '',
+ defaultMap,
+ TYPES.map(details => customMap(details)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.opts.js
new file mode 100644
index 000000000..d26ab05b2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableMap.opts.js
@@ -0,0 +1,19 @@
+const { capitalize } = require('../../helpers');
+
+const mapType = str => (str == 'uint256' ? 'Uint' : capitalize(str));
+
+const formatType = (keyType, valueType) => ({
+ name: `${mapType(keyType)}To${mapType(valueType)}Map`,
+ keyType,
+ valueType,
+});
+
+const TYPES = ['uint256', 'address', 'bytes32']
+ .flatMap((key, _, array) => array.map(value => [key, value]))
+ .slice(0, -1) // remove bytes32 → byte32 (last one) that is already defined
+ .map(args => formatType(...args));
+
+module.exports = {
+ TYPES,
+ formatType,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.js
new file mode 100644
index 000000000..02eccd0df
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.js
@@ -0,0 +1,247 @@
+const format = require('../format-lines');
+const { fromBytes32, toBytes32 } = require('./conversion');
+const { TYPES } = require('./EnumerableSet.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Library for managing
+ * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
+ * types.
+ *
+ * Sets have the following properties:
+ *
+ * - Elements are added, removed, and checked for existence in constant time
+ * (O(1)).
+ * - Elements are enumerated in O(n). No guarantees are made on the ordering.
+ *
+ * \`\`\`solidity
+ * contract Example {
+ * // Add the library methods
+ * using EnumerableSet for EnumerableSet.AddressSet;
+ *
+ * // Declare a set state variable
+ * EnumerableSet.AddressSet private mySet;
+ * }
+ * \`\`\`
+ *
+ * As of v3.3.0, sets of type \`bytes32\` (\`Bytes32Set\`), \`address\` (\`AddressSet\`)
+ * and \`uint256\` (\`UintSet\`) are supported.
+ *
+ * [WARNING]
+ * ====
+ * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
+ * unusable.
+ * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
+ *
+ * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
+ * array of EnumerableSet.
+ * ====
+ */
+`;
+
+const defaultSet = `\
+// To implement this library for multiple types with as little code
+// repetition as possible, we write it in terms of a generic Set type with
+// bytes32 values.
+// The Set implementation uses private functions, and user-facing
+// implementations (such as AddressSet) are just wrappers around the
+// underlying Set.
+// This means that we can only create new EnumerableSets for types that fit
+// in bytes32.
+
+struct Set {
+ // Storage of set values
+ bytes32[] _values;
+ // Position is the index of the value in the \`values\` array plus 1.
+ // Position 0 is used to mean a value is not in the set.
+ mapping(bytes32 value => uint256) _positions;
+}
+
+/**
+ * @dev Add a value to a set. O(1).
+ *
+ * Returns true if the value was added to the set, that is if it was not
+ * already present.
+ */
+function _add(Set storage set, bytes32 value) private returns (bool) {
+ if (!_contains(set, value)) {
+ set._values.push(value);
+ // The value is stored at length-1, but we add 1 to all indexes
+ // and use 0 as a sentinel value
+ set._positions[value] = set._values.length;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * @dev Removes a value from a set. O(1).
+ *
+ * Returns true if the value was removed from the set, that is if it was
+ * present.
+ */
+function _remove(Set storage set, bytes32 value) private returns (bool) {
+ // We cache the value's position to prevent multiple reads from the same storage slot
+ uint256 position = set._positions[value];
+
+ if (position != 0) {
+ // Equivalent to contains(set, value)
+ // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
+ // the array, and then remove the last element (sometimes called as 'swap and pop').
+ // This modifies the order of the array, as noted in {at}.
+
+ uint256 valueIndex = position - 1;
+ uint256 lastIndex = set._values.length - 1;
+
+ if (valueIndex != lastIndex) {
+ bytes32 lastValue = set._values[lastIndex];
+
+ // Move the lastValue to the index where the value to delete is
+ set._values[valueIndex] = lastValue;
+ // Update the tracked position of the lastValue (that was just moved)
+ set._positions[lastValue] = position;
+ }
+
+ // Delete the slot where the moved value was stored
+ set._values.pop();
+
+ // Delete the tracked position for the deleted slot
+ delete set._positions[value];
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * @dev Returns true if the value is in the set. O(1).
+ */
+function _contains(Set storage set, bytes32 value) private view returns (bool) {
+ return set._positions[value] != 0;
+}
+
+/**
+ * @dev Returns the number of values on the set. O(1).
+ */
+function _length(Set storage set) private view returns (uint256) {
+ return set._values.length;
+}
+
+/**
+ * @dev Returns the value stored at position \`index\` in the set. O(1).
+ *
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - \`index\` must be strictly less than {length}.
+ */
+function _at(Set storage set, uint256 index) private view returns (bytes32) {
+ return set._values[index];
+}
+
+/**
+ * @dev Return the entire set in an array
+ *
+ * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
+ * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
+ * this function has an unbounded cost, and using it as part of a state-changing function may render the function
+ * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
+ */
+function _values(Set storage set) private view returns (bytes32[] memory) {
+ return set._values;
+}
+`;
+
+const customSet = ({ name, type }) => `\
+// ${name}
+
+struct ${name} {
+ Set _inner;
+}
+
+/**
+ * @dev Add a value to a set. O(1).
+ *
+ * Returns true if the value was added to the set, that is if it was not
+ * already present.
+ */
+function add(${name} storage set, ${type} value) internal returns (bool) {
+ return _add(set._inner, ${toBytes32(type, 'value')});
+}
+
+/**
+ * @dev Removes a value from a set. O(1).
+ *
+ * Returns true if the value was removed from the set, that is if it was
+ * present.
+ */
+function remove(${name} storage set, ${type} value) internal returns (bool) {
+ return _remove(set._inner, ${toBytes32(type, 'value')});
+}
+
+/**
+ * @dev Returns true if the value is in the set. O(1).
+ */
+function contains(${name} storage set, ${type} value) internal view returns (bool) {
+ return _contains(set._inner, ${toBytes32(type, 'value')});
+}
+
+/**
+ * @dev Returns the number of values in the set. O(1).
+ */
+function length(${name} storage set) internal view returns (uint256) {
+ return _length(set._inner);
+}
+
+/**
+ * @dev Returns the value stored at position \`index\` in the set. O(1).
+ *
+ * Note that there are no guarantees on the ordering of values inside the
+ * array, and it may change when more values are added or removed.
+ *
+ * Requirements:
+ *
+ * - \`index\` must be strictly less than {length}.
+ */
+function at(${name} storage set, uint256 index) internal view returns (${type}) {
+ return ${fromBytes32(type, '_at(set._inner, index)')};
+}
+
+/**
+ * @dev Return the entire set in an array
+ *
+ * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
+ * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
+ * this function has an unbounded cost, and using it as part of a state-changing function may render the function
+ * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
+ */
+function values(${name} storage set) internal view returns (${type}[] memory) {
+ bytes32[] memory store = _values(set._inner);
+ ${type}[] memory result;
+
+ assembly ("memory-safe") {
+ result := store
+ }
+
+ return result;
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library EnumerableSet {',
+ format(
+ [].concat(
+ defaultSet,
+ TYPES.map(details => customSet(details)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.opts.js
new file mode 100644
index 000000000..739f0acdf
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/EnumerableSet.opts.js
@@ -0,0 +1,12 @@
+const { capitalize } = require('../../helpers');
+
+const mapType = str => (str == 'uint256' ? 'Uint' : capitalize(str));
+
+const formatType = type => ({
+ name: `${mapType(type)}Set`,
+ type,
+});
+
+const TYPES = ['bytes32', 'address', 'uint256'].map(formatType);
+
+module.exports = { TYPES, formatType };
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.js
new file mode 100644
index 000000000..890b2feba
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.js
@@ -0,0 +1,187 @@
+const format = require('../format-lines');
+const { OPTS } = require('./MerkleProof.opts');
+
+const DEFAULT_HASH = 'Hashes.commutativeKeccak256';
+
+const formatArgsSingleLine = (...args) => args.filter(Boolean).join(', ');
+const formatArgsMultiline = (...args) => '\n' + format(args.filter(Boolean).join(',\0').split('\0'));
+
+// TEMPLATE
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Hashes} from "./Hashes.sol";
+
+/**
+ * @dev These functions deal with verification of Merkle Tree proofs.
+ *
+ * The tree and the proofs can be generated using our
+ * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
+ * You will find a quickstart guide in the readme.
+ *
+ * WARNING: You should avoid using leaf values that are 64 bytes long prior to
+ * hashing, or use a hash function other than keccak256 for hashing leaves.
+ * This is because the concatenation of a sorted pair of internal nodes in
+ * the Merkle tree could be reinterpreted as a leaf value.
+ * OpenZeppelin's JavaScript library generates Merkle trees that are safe
+ * against this attack out of the box.
+ *
+ * IMPORTANT: Consider memory side-effects when using custom hashing functions
+ * that access memory in an unsafe way.
+ *
+ * NOTE: This library supports proof verification for merkle trees built using
+ * custom _commutative_ hashing functions (i.e. \`H(a, b) == H(b, a)\`). Proving
+ * leaf inclusion in trees built using non-commutative hashing functions requires
+ * additional logic that is not supported by this library.
+ */
+`;
+
+const errors = `\
+/**
+ *@dev The multiproof provided is not valid.
+ */
+error MerkleProofInvalidMultiproof();
+`;
+
+const templateProof = ({ suffix, location, visibility, hash }) => `\
+/**
+ * @dev Returns true if a \`leaf\` can be proved to be a part of a Merkle tree
+ * defined by \`root\`. For this, a \`proof\` must be provided, containing
+ * sibling hashes on the branch from the leaf to the root of the tree. Each
+ * pair of leaves and each pair of pre-images are assumed to be sorted.
+ *
+ * This version handles proofs in ${location} with ${hash ? 'a custom' : 'the default'} hashing function.
+ */
+function verify${suffix}(${(hash ? formatArgsMultiline : formatArgsSingleLine)(
+ `bytes32[] ${location} proof`,
+ 'bytes32 root',
+ 'bytes32 leaf',
+ hash && `function(bytes32, bytes32) view returns (bytes32) ${hash}`,
+)}) internal ${visibility} returns (bool) {
+ return processProof${suffix}(proof, leaf${hash ? `, ${hash}` : ''}) == root;
+}
+
+/**
+ * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
+ * from \`leaf\` using \`proof\`. A \`proof\` is valid if and only if the rebuilt
+ * hash matches the root of the tree. When processing the proof, the pairs
+ * of leaves & pre-images are assumed to be sorted.
+ *
+ * This version handles proofs in ${location} with ${hash ? 'a custom' : 'the default'} hashing function.
+ */
+function processProof${suffix}(${(hash ? formatArgsMultiline : formatArgsSingleLine)(
+ `bytes32[] ${location} proof`,
+ 'bytes32 leaf',
+ hash && `function(bytes32, bytes32) view returns (bytes32) ${hash}`,
+)}) internal ${visibility} returns (bytes32) {
+ bytes32 computedHash = leaf;
+ for (uint256 i = 0; i < proof.length; i++) {
+ computedHash = ${hash ?? DEFAULT_HASH}(computedHash, proof[i]);
+ }
+ return computedHash;
+}
+`;
+
+const templateMultiProof = ({ suffix, location, visibility, hash }) => `\
+/**
+ * @dev Returns true if the \`leaves\` can be simultaneously proven to be a part of a Merkle tree defined by
+ * \`root\`, according to \`proof\` and \`proofFlags\` as described in {processMultiProof}.
+ *
+ * This version handles multiproofs in ${location} with ${hash ? 'a custom' : 'the default'} hashing function.
+ *
+ * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details.
+ *
+ * NOTE: Consider the case where \`root == proof[0] && leaves.length == 0\` as it will return \`true\`.
+ * The \`leaves\` must be validated independently. See {processMultiProof${suffix}}.
+ */
+function multiProofVerify${suffix}(${formatArgsMultiline(
+ `bytes32[] ${location} proof`,
+ `bool[] ${location} proofFlags`,
+ 'bytes32 root',
+ `bytes32[] memory leaves`,
+ hash && `function(bytes32, bytes32) view returns (bytes32) ${hash}`,
+)}) internal ${visibility} returns (bool) {
+ return processMultiProof${suffix}(proof, proofFlags, leaves${hash ? `, ${hash}` : ''}) == root;
+}
+
+/**
+ * @dev Returns the root of a tree reconstructed from \`leaves\` and sibling nodes in \`proof\`. The reconstruction
+ * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
+ * leaf/inner node or a proof sibling node, depending on whether each \`proofFlags\` item is true or false
+ * respectively.
+ *
+ * This version handles multiproofs in ${location} with ${hash ? 'a custom' : 'the default'} hashing function.
+ *
+ * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
+ * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
+ * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
+ *
+ * NOTE: The _empty set_ (i.e. the case where \`proof.length == 1 && leaves.length == 0\`) is considered a no-op,
+ * and therefore a valid multiproof (i.e. it returns \`proof[0]\`). Consider disallowing this case if you're not
+ * validating the leaves elsewhere.
+ */
+function processMultiProof${suffix}(${formatArgsMultiline(
+ `bytes32[] ${location} proof`,
+ `bool[] ${location} proofFlags`,
+ `bytes32[] memory leaves`,
+ hash && `function(bytes32, bytes32) view returns (bytes32) ${hash}`,
+)}) internal ${visibility} returns (bytes32 merkleRoot) {
+ // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
+ // consuming and producing values on a queue. The queue starts with the \`leaves\` array, then goes onto the
+ // \`hashes\` array. At the end of the process, the last hash in the \`hashes\` array should contain the root of
+ // the Merkle tree.
+ uint256 leavesLen = leaves.length;
+ uint256 proofFlagsLen = proofFlags.length;
+
+ // Check proof validity.
+ if (leavesLen + proof.length != proofFlagsLen + 1) {
+ revert MerkleProofInvalidMultiproof();
+ }
+
+ // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
+ // \`xxx[xxxPos++]\`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
+ bytes32[] memory hashes = new bytes32[](proofFlagsLen);
+ uint256 leafPos = 0;
+ uint256 hashPos = 0;
+ uint256 proofPos = 0;
+ // At each step, we compute the next hash using two values:
+ // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
+ // get the next hash.
+ // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
+ // \`proof\` array.
+ for (uint256 i = 0; i < proofFlagsLen; i++) {
+ bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
+ bytes32 b = proofFlags[i]
+ ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
+ : proof[proofPos++];
+ hashes[i] = ${hash ?? DEFAULT_HASH}(a, b);
+ }
+
+ if (proofFlagsLen > 0) {
+ if (proofPos != proof.length) {
+ revert MerkleProofInvalidMultiproof();
+ }
+ unchecked {
+ return hashes[proofFlagsLen - 1];
+ }
+ } else if (leavesLen > 0) {
+ return leaves[0];
+ } else {
+ return proof[0];
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library MerkleProof {',
+ format(
+ [].concat(
+ errors,
+ OPTS.flatMap(opts => templateProof(opts)),
+ OPTS.flatMap(opts => templateMultiProof(opts)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.opts.js
new file mode 100644
index 000000000..911f23922
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/MerkleProof.opts.js
@@ -0,0 +1,11 @@
+const { product } = require('../../helpers');
+
+const OPTS = product(
+ [
+ { suffix: '', location: 'memory' },
+ { suffix: 'Calldata', location: 'calldata' },
+ ],
+ [{ visibility: 'pure' }, { visibility: 'view', hash: 'hasher' }],
+).map(objs => Object.assign({}, ...objs));
+
+module.exports = { OPTS };
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.js
new file mode 100644
index 000000000..9f3b7716a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.js
@@ -0,0 +1,92 @@
+const format = require('../format-lines');
+const sanitize = require('../helpers/sanitize');
+const { product } = require('../../helpers');
+const { SIZES } = require('./Packing.opts');
+
+// TEMPLATE
+const header = `\
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Helper library packing and unpacking multiple values into bytesXX.
+ *
+ * Example usage:
+ *
+ * \`\`\`solidity
+ * library MyPacker {
+ * type MyType is bytes32;
+ *
+ * function _pack(address account, bytes4 selector, uint64 period) external pure returns (MyType) {
+ * bytes12 subpack = Packing.pack_4_8(selector, bytes8(period));
+ * bytes32 pack = Packing.pack_20_12(bytes20(account), subpack);
+ * return MyType.wrap(pack);
+ * }
+ *
+ * function _unpack(MyType self) external pure returns (address, bytes4, uint64) {
+ * bytes32 pack = MyType.unwrap(self);
+ * return (
+ * address(Packing.extract_32_20(pack, 0)),
+ * Packing.extract_32_4(pack, 20),
+ * uint64(Packing.extract_32_8(pack, 24))
+ * );
+ * }
+ * }
+ * \`\`\`
+ *
+ * _Available since v5.1._
+ */
+// solhint-disable func-name-mixedcase
+`;
+
+const errors = `\
+error OutOfRangeAccess();
+`;
+
+const pack = (left, right) => `\
+function pack_${left}_${right}(bytes${left} left, bytes${right} right) internal pure returns (bytes${
+ left + right
+} result) {
+ assembly ("memory-safe") {
+ left := ${sanitize.bytes('left', left)}
+ right := ${sanitize.bytes('right', right)}
+ result := or(left, shr(${8 * left}, right))
+ }
+}
+`;
+
+const extract = (outer, inner) => `\
+function extract_${outer}_${inner}(bytes${outer} self, uint8 offset) internal pure returns (bytes${inner} result) {
+ if (offset > ${outer - inner}) revert OutOfRangeAccess();
+ assembly ("memory-safe") {
+ result := ${sanitize.bytes('shl(mul(8, offset), self)', inner)}
+ }
+}
+`;
+
+const replace = (outer, inner) => `\
+function replace_${outer}_${inner}(bytes${outer} self, bytes${inner} value, uint8 offset) internal pure returns (bytes${outer} result) {
+ bytes${inner} oldValue = extract_${outer}_${inner}(self, offset);
+ assembly ("memory-safe") {
+ value := ${sanitize.bytes('value', inner)}
+ result := xor(self, shr(mul(8, offset), xor(oldValue, value)))
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library Packing {',
+ format(
+ [].concat(
+ errors,
+ product(SIZES, SIZES)
+ .filter(([left, right]) => SIZES.includes(left + right))
+ .map(([left, right]) => pack(left, right)),
+ product(SIZES, SIZES)
+ .filter(([outer, inner]) => outer > inner)
+ .flatMap(([outer, inner]) => [extract(outer, inner), replace(outer, inner)]),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.opts.js
new file mode 100644
index 000000000..893ad6297
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.opts.js
@@ -0,0 +1,3 @@
+module.exports = {
+ SIZES: [1, 2, 4, 6, 8, 10, 12, 16, 20, 22, 24, 28, 32],
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.t.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.t.js
new file mode 100644
index 000000000..1feec28f5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Packing.t.js
@@ -0,0 +1,48 @@
+const format = require('../format-lines');
+const { product } = require('../../helpers');
+const { SIZES } = require('./Packing.opts');
+
+// TEMPLATE
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Packing} from "@openzeppelin/contracts/utils/Packing.sol";
+`;
+
+const testPack = (left, right) => `\
+function testPack(bytes${left} left, bytes${right} right) external pure {
+ assertEq(left, Packing.pack_${left}_${right}(left, right).extract_${left + right}_${left}(0));
+ assertEq(right, Packing.pack_${left}_${right}(left, right).extract_${left + right}_${right}(${left}));
+}
+`;
+
+const testReplace = (outer, inner) => `\
+function testReplace(bytes${outer} container, bytes${inner} newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, ${outer - inner}));
+
+ bytes${inner} oldValue = container.extract_${outer}_${inner}(offset);
+
+ assertEq(newValue, container.replace_${outer}_${inner}(newValue, offset).extract_${outer}_${inner}(offset));
+ assertEq(container, container.replace_${outer}_${inner}(newValue, offset).replace_${outer}_${inner}(oldValue, offset));
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header,
+ 'contract PackingTest is Test {',
+ format(
+ [].concat(
+ 'using Packing for *;',
+ '',
+ product(SIZES, SIZES)
+ .filter(([left, right]) => SIZES.includes(left + right))
+ .map(([left, right]) => testPack(left, right)),
+ product(SIZES, SIZES)
+ .filter(([outer, inner]) => outer > inner)
+ .map(([outer, inner]) => testReplace(outer, inner)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SafeCast.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SafeCast.js
new file mode 100644
index 000000000..21000cf4a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SafeCast.js
@@ -0,0 +1,136 @@
+const format = require('../format-lines');
+const { range } = require('../../helpers');
+
+const LENGTHS = range(8, 256, 8).reverse(); // 248 → 8 (in steps of 8)
+
+const header = `\
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
+ * checks.
+ *
+ * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
+ * easily result in undesired exploitation or bugs, since developers usually
+ * assume that overflows raise errors. \`SafeCast\` restores this intuition by
+ * reverting the transaction when such an operation overflows.
+ *
+ * Using this library instead of the unchecked operations eliminates an entire
+ * class of bugs, so it's recommended to use it always.
+ */
+`;
+
+const errors = `\
+/**
+ * @dev Value doesn't fit in an uint of \`bits\` size.
+ */
+error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
+
+/**
+ * @dev An int value doesn't fit in an uint of \`bits\` size.
+ */
+error SafeCastOverflowedIntToUint(int256 value);
+
+/**
+ * @dev Value doesn't fit in an int of \`bits\` size.
+ */
+error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
+
+/**
+ * @dev An uint value doesn't fit in an int of \`bits\` size.
+ */
+error SafeCastOverflowedUintToInt(uint256 value);
+`;
+
+const toUintDownCast = length => `\
+/**
+ * @dev Returns the downcasted uint${length} from uint256, reverting on
+ * overflow (when the input is greater than largest uint${length}).
+ *
+ * Counterpart to Solidity's \`uint${length}\` operator.
+ *
+ * Requirements:
+ *
+ * - input must fit into ${length} bits
+ */
+function toUint${length}(uint256 value) internal pure returns (uint${length}) {
+ if (value > type(uint${length}).max) {
+ revert SafeCastOverflowedUintDowncast(${length}, value);
+ }
+ return uint${length}(value);
+}
+`;
+
+const toIntDownCast = length => `\
+/**
+ * @dev Returns the downcasted int${length} from int256, reverting on
+ * overflow (when the input is less than smallest int${length} or
+ * greater than largest int${length}).
+ *
+ * Counterpart to Solidity's \`int${length}\` operator.
+ *
+ * Requirements:
+ *
+ * - input must fit into ${length} bits
+ */
+function toInt${length}(int256 value) internal pure returns (int${length} downcasted) {
+ downcasted = int${length}(value);
+ if (downcasted != value) {
+ revert SafeCastOverflowedIntDowncast(${length}, value);
+ }
+}
+`;
+
+const toInt = length => `\
+/**
+ * @dev Converts an unsigned uint${length} into a signed int${length}.
+ *
+ * Requirements:
+ *
+ * - input must be less than or equal to maxInt${length}.
+ */
+function toInt${length}(uint${length} value) internal pure returns (int${length}) {
+ // Note: Unsafe cast below is okay because \`type(int${length}).max\` is guaranteed to be positive
+ if (value > uint${length}(type(int${length}).max)) {
+ revert SafeCastOverflowedUintToInt(value);
+ }
+ return int${length}(value);
+}
+`;
+
+const toUint = length => `\
+/**
+ * @dev Converts a signed int${length} into an unsigned uint${length}.
+ *
+ * Requirements:
+ *
+ * - input must be greater than or equal to 0.
+ */
+function toUint${length}(int${length} value) internal pure returns (uint${length}) {
+ if (value < 0) {
+ revert SafeCastOverflowedIntToUint(value);
+ }
+ return uint${length}(value);
+}
+`;
+
+const boolToUint = `\
+/**
+ * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
+ */
+function toUint(bool b) internal pure returns (uint256 u) {
+ assembly ("memory-safe") {
+ u := iszero(iszero(b))
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library SafeCast {',
+ format(
+ [].concat(errors, LENGTHS.map(toUintDownCast), toUint(256), LENGTHS.map(toIntDownCast), toInt(256), boolToUint),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Slot.opts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Slot.opts.js
new file mode 100644
index 000000000..3eca2bcf0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/Slot.opts.js
@@ -0,0 +1,15 @@
+const { capitalize } = require('../../helpers');
+
+const TYPES = [
+ { type: 'address', isValueType: true },
+ { type: 'bool', isValueType: true, name: 'Boolean' },
+ { type: 'bytes32', isValueType: true, variants: ['bytes4'] },
+ { type: 'uint256', isValueType: true, variants: ['uint32'] },
+ { type: 'int256', isValueType: true, variants: ['int32'] },
+ { type: 'string', isValueType: false },
+ { type: 'bytes', isValueType: false },
+].map(type => Object.assign(type, { name: type.name ?? capitalize(type.type) }));
+
+Object.assign(TYPES, Object.fromEntries(TYPES.map(entry => [entry.type, entry])));
+
+module.exports = { TYPES };
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.js
new file mode 100644
index 000000000..ec4d244b9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.js
@@ -0,0 +1,119 @@
+const format = require('../format-lines');
+const sanitize = require('../helpers/sanitize');
+const { TYPES } = require('./Slot.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
+ * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
+ * the solidity language / compiler.
+ *
+ * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
+ *
+ * Example usage:
+ * \`\`\`solidity
+ * contract Example {
+ * // Add the library methods
+ * using StorageSlot for bytes32;
+ * using SlotDerivation for bytes32;
+ *
+ * // Declare a namespace
+ * string private constant _NAMESPACE = "" // eg. OpenZeppelin.Slot
+ *
+ * function setValueInNamespace(uint256 key, address newValue) internal {
+ * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
+ * }
+ *
+ * function getValueInNamespace(uint256 key) internal view returns (address) {
+ * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
+ * }
+ * }
+ * \`\`\`
+ *
+ * TIP: Consider using this library along with {StorageSlot}.
+ *
+ * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
+ * upgrade safety will ignore the slots accessed through this library.
+ *
+ * _Available since v5.1._
+ */
+`;
+
+const namespace = `\
+/**
+ * @dev Derive an ERC-7201 slot from a string (namespace).
+ */
+function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
+ assembly ("memory-safe") {
+ mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
+ slot := and(keccak256(0x00, 0x20), not(0xff))
+ }
+}
+`;
+
+const array = `\
+/**
+ * @dev Add an offset to a slot to get the n-th element of a structure or an array.
+ */
+function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
+ unchecked {
+ return bytes32(uint256(slot) + pos);
+ }
+}
+
+/**
+ * @dev Derive the location of the first element in an array from the slot where the length is stored.
+ */
+function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
+ assembly ("memory-safe") {
+ mstore(0x00, slot)
+ result := keccak256(0x00, 0x20)
+ }
+}
+`;
+
+const mapping = ({ type }) => `\
+/**
+ * @dev Derive the location of a mapping element from the key.
+ */
+function deriveMapping(bytes32 slot, ${type} key) internal pure returns (bytes32 result) {
+ assembly ("memory-safe") {
+ mstore(0x00, ${(sanitize[type] ?? (x => x))('key')})
+ mstore(0x20, slot)
+ result := keccak256(0x00, 0x40)
+ }
+}
+`;
+
+const mapping2 = ({ type }) => `\
+/**
+ * @dev Derive the location of a mapping element from the key.
+ */
+function deriveMapping(bytes32 slot, ${type} memory key) internal pure returns (bytes32 result) {
+ assembly ("memory-safe") {
+ let length := mload(key)
+ let begin := add(key, 0x20)
+ let end := add(begin, length)
+ let cache := mload(end)
+ mstore(end, slot)
+ result := keccak256(begin, add(length, 0x20))
+ mstore(end, cache)
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library SlotDerivation {',
+ format(
+ [].concat(
+ namespace,
+ array,
+ TYPES.map(type => (type.isValueType ? mapping(type) : mapping2(type))),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.t.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.t.js
new file mode 100644
index 000000000..f03e1fc25
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/SlotDerivation.t.js
@@ -0,0 +1,127 @@
+const format = require('../format-lines');
+const { capitalize } = require('../../helpers');
+const { TYPES } = require('./Slot.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {SymTest} from "halmos-cheatcodes/SymTest.sol";
+import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol";
+`;
+
+const array = `\
+bytes[] private _array;
+
+function symbolicDeriveArray(uint256 length, uint256 offset) public {
+ vm.assume(length > 0);
+ vm.assume(offset < length);
+ _assertDeriveArray(length, offset);
+}
+
+function testDeriveArray(uint256 length, uint256 offset) public {
+ length = bound(length, 1, type(uint256).max);
+ offset = bound(offset, 0, length - 1);
+ _assertDeriveArray(length, offset);
+}
+
+function _assertDeriveArray(uint256 length, uint256 offset) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _array.slot
+ sstore(baseSlot, length) // store length so solidity access does not revert
+ }
+
+ bytes storage derived = _array[offset];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveArray().offset(offset), derivedSlot);
+}
+`;
+
+const mapping = ({ type, name }) => `\
+mapping(${type} => bytes) private _${type}Mapping;
+
+function testSymbolicDeriveMapping${name}(${type} key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _${type}Mapping.slot
+ }
+
+ bytes storage derived = _${type}Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+}
+`;
+
+const mappingDirty = ({ type, name }) => `\
+function testSymbolicDeriveMapping${name}Dirty(bytes32 dirtyKey) public {
+ ${type} key;
+ assembly {
+ key := dirtyKey
+ }
+
+ // run the "normal" test using a potentially dirty value
+ testSymbolicDeriveMapping${name}(key);
+}
+`;
+
+const boundedMapping = ({ type, name }) => `\
+mapping(${type} => bytes) private _${type}Mapping;
+
+function testDeriveMapping${name}(${type} memory key) public {
+ _assertDeriveMapping${name}(key);
+}
+
+function symbolicDeriveMapping${name}() public {
+ _assertDeriveMapping${name}(svm.create${name}(256, "DeriveMapping${name}Input"));
+}
+
+function _assertDeriveMapping${name}(${type} memory key) internal {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _${type}Mapping.slot
+ }
+
+ bytes storage derived = _${type}Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header,
+ 'contract SlotDerivationTest is Test, SymTest {',
+ format(
+ [].concat(
+ 'using SlotDerivation for bytes32;',
+ '',
+ array,
+ TYPES.flatMap(type =>
+ [].concat(
+ type,
+ (type.variants ?? []).map(variant => ({
+ type: variant,
+ name: capitalize(variant),
+ isValueType: type.isValueType,
+ })),
+ ),
+ ).map(type => (type.isValueType ? mapping(type) : boundedMapping(type))),
+ mappingDirty(TYPES.bool),
+ mappingDirty(TYPES.address),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlot.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlot.js
new file mode 100644
index 000000000..53287b81f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlot.js
@@ -0,0 +1,77 @@
+const format = require('../format-lines');
+const { TYPES } = require('./Slot.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Library for reading and writing primitive types to specific storage slots.
+ *
+ * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
+ * This library helps with reading and writing to such slots without the need for inline assembly.
+ *
+ * The functions in this library return Slot structs that contain a \`value\` member that can be used to read or write.
+ *
+ * Example usage to set ERC-1967 implementation slot:
+ * \`\`\`solidity
+ * contract ERC1967 {
+ * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
+ * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
+ *
+ * function _getImplementation() internal view returns (address) {
+ * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
+ * }
+ *
+ * function _setImplementation(address newImplementation) internal {
+ * require(newImplementation.code.length > 0);
+ * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
+ * }
+ * }
+ * \`\`\`
+ *
+ * TIP: Consider using this library along with {SlotDerivation}.
+ */
+`;
+
+const struct = ({ type, name }) => `\
+struct ${name}Slot {
+ ${type} value;
+}
+`;
+
+const get = ({ name }) => `\
+/**
+ * @dev Returns ${
+ name.toLowerCase().startsWith('a') ? 'an' : 'a'
+ } \`${name}Slot\` with member \`value\` located at \`slot\`.
+ */
+function get${name}Slot(bytes32 slot) internal pure returns (${name}Slot storage r) {
+ assembly ("memory-safe") {
+ r.slot := slot
+ }
+}
+`;
+
+const getStorage = ({ type, name }) => `\
+/**
+ * @dev Returns an \`${name}Slot\` representation of the ${type} storage pointer \`store\`.
+ */
+function get${name}Slot(${type} storage store) internal pure returns (${name}Slot storage r) {
+ assembly ("memory-safe") {
+ r.slot := store.slot
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library StorageSlot {',
+ format(
+ [].concat(
+ TYPES.map(type => struct(type)),
+ TYPES.flatMap(type => [get(type), !type.isValueType && getStorage(type)].filter(Boolean)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlotMock.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlotMock.js
new file mode 100644
index 000000000..c6d326a5e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/StorageSlotMock.js
@@ -0,0 +1,57 @@
+const format = require('../format-lines');
+const { TYPES } = require('./Slot.opts');
+
+const header = `\
+pragma solidity ^0.8.20;
+
+import {Multicall} from "../utils/Multicall.sol";
+import {StorageSlot} from "../utils/StorageSlot.sol";
+`;
+
+const storageSetValueType = ({ type, name }) => `\
+function set${name}Slot(bytes32 slot, ${type} value) public {
+ slot.get${name}Slot().value = value;
+}
+`;
+
+const storageGetValueType = ({ type, name }) => `\
+function get${name}Slot(bytes32 slot) public view returns (${type}) {
+ return slot.get${name}Slot().value;
+}
+`;
+
+const storageSetNonValueType = ({ type, name }) => `\
+mapping(uint256 key => ${type}) public ${type}Map;
+
+function set${name}Slot(bytes32 slot, ${type} calldata value) public {
+ slot.get${name}Slot().value = value;
+}
+
+function set${name}Storage(uint256 key, ${type} calldata value) public {
+ ${type}Map[key].get${name}Slot().value = value;
+}
+
+function get${name}Slot(bytes32 slot) public view returns (${type} memory) {
+ return slot.get${name}Slot().value;
+}
+
+function get${name}Storage(uint256 key) public view returns (${type} memory) {
+ return ${type}Map[key].get${name}Slot().value;
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header,
+ 'contract StorageSlotMock is Multicall {',
+ format(
+ [].concat(
+ 'using StorageSlot for *;',
+ '',
+ TYPES.filter(type => type.isValueType).map(type => storageSetValueType(type)),
+ TYPES.filter(type => type.isValueType).map(type => storageGetValueType(type)),
+ TYPES.filter(type => !type.isValueType).map(type => storageSetNonValueType(type)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlot.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlot.js
new file mode 100644
index 000000000..8e291bc13
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlot.js
@@ -0,0 +1,80 @@
+const format = require('../format-lines');
+const { TYPES } = require('./Slot.opts');
+
+const header = `\
+pragma solidity ^0.8.24;
+
+/**
+ * @dev Library for reading and writing value-types to specific transient storage slots.
+ *
+ * Transient slots are often used to store temporary values that are removed after the current transaction.
+ * This library helps with reading and writing to such slots without the need for inline assembly.
+ *
+ * * Example reading and writing values using transient storage:
+ * \`\`\`solidity
+ * contract Lock {
+ * using TransientSlot for *;
+ *
+ * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
+ * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
+ *
+ * modifier locked() {
+ * require(!_LOCK_SLOT.asBoolean().tload());
+ *
+ * _LOCK_SLOT.asBoolean().tstore(true);
+ * _;
+ * _LOCK_SLOT.asBoolean().tstore(false);
+ * }
+ * }
+ * \`\`\`
+ *
+ * TIP: Consider using this library along with {SlotDerivation}.
+ */
+`;
+
+const udvt = ({ type, name }) => `\
+/**
+ * @dev UDVT that represent a slot holding a ${type}.
+ */
+type ${name}Slot is bytes32;
+
+/**
+ * @dev Cast an arbitrary slot to a ${name}Slot.
+ */
+function as${name}(bytes32 slot) internal pure returns (${name}Slot) {
+ return ${name}Slot.wrap(slot);
+}
+`;
+
+const transient = ({ type, name }) => `\
+/**
+ * @dev Load the value held at location \`slot\` in transient storage.
+ */
+function tload(${name}Slot slot) internal view returns (${type} value) {
+ assembly ("memory-safe") {
+ value := tload(slot)
+ }
+}
+
+/**
+ * @dev Store \`value\` at location \`slot\` in transient storage.
+ */
+function tstore(${name}Slot slot, ${type} value) internal {
+ assembly ("memory-safe") {
+ tstore(slot, value)
+ }
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header.trimEnd(),
+ 'library TransientSlot {',
+ format(
+ [].concat(
+ TYPES.filter(type => type.isValueType).map(type => udvt(type)),
+ TYPES.filter(type => type.isValueType).map(type => transient(type)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlotMock.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlotMock.js
new file mode 100644
index 000000000..4807b0cc1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/TransientSlotMock.js
@@ -0,0 +1,35 @@
+const format = require('../format-lines');
+const { TYPES } = require('./Slot.opts');
+
+const header = `\
+pragma solidity ^0.8.24;
+
+import {Multicall} from "../utils/Multicall.sol";
+import {TransientSlot} from "../utils/TransientSlot.sol";
+`;
+
+const transient = ({ type, name }) => `\
+event ${name}Value(bytes32 slot, ${type} value);
+
+function tload${name}(bytes32 slot) public {
+ emit ${name}Value(slot, slot.as${name}().tload());
+}
+
+function tstore(bytes32 slot, ${type} value) public {
+ slot.as${name}().tstore(value);
+}
+`;
+
+// GENERATE
+module.exports = format(
+ header,
+ 'contract TransientSlotMock is Multicall {',
+ format(
+ [].concat(
+ 'using TransientSlot for *;',
+ '',
+ TYPES.filter(type => type.isValueType).map(type => transient(type)),
+ ),
+ ).trimEnd(),
+ '}',
+);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/conversion.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/conversion.js
new file mode 100644
index 000000000..9221f7c21
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/generate/templates/conversion.js
@@ -0,0 +1,30 @@
+function toBytes32(type, value) {
+ switch (type) {
+ case 'bytes32':
+ return value;
+ case 'uint256':
+ return `bytes32(${value})`;
+ case 'address':
+ return `bytes32(uint256(uint160(${value})))`;
+ default:
+ throw new Error(`Conversion from ${type} to bytes32 not supported`);
+ }
+}
+
+function fromBytes32(type, value) {
+ switch (type) {
+ case 'bytes32':
+ return value;
+ case 'uint256':
+ return `uint256(${value})`;
+ case 'address':
+ return `address(uint160(uint256(${value})))`;
+ default:
+ throw new Error(`Conversion from bytes32 to ${type} not supported`);
+ }
+}
+
+module.exports = {
+ toBytes32,
+ fromBytes32,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/git-user-config.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/git-user-config.sh
new file mode 100644
index 000000000..e7b81c3eb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/git-user-config.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+set -euo pipefail -x
+
+git config user.name 'github-actions'
+git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/helpers.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/helpers.js
new file mode 100644
index 000000000..d28c0866d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/helpers.js
@@ -0,0 +1,7 @@
+const iterate = require('../test/helpers/iterate');
+const strings = require('../test/helpers/strings');
+
+module.exports = {
+ ...iterate,
+ ...strings,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepack.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepack.sh
new file mode 100644
index 000000000..6af10329f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepack.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+shopt -s globstar
+
+# cross platform `mkdir -p`
+mkdirp() {
+ node -e "fs.mkdirSync('$1', { recursive: true })"
+}
+
+# cd to the root of the repo
+cd "$(git rev-parse --show-toplevel)"
+
+npm run clean
+
+env COMPILE_MODE=production npm run compile
+
+mkdirp contracts/build/contracts
+cp artifacts/contracts/**/*.json contracts/build/contracts
+rm contracts/build/contracts/*.dbg.json
+node scripts/remove-ignored-artifacts.js
+
+cp README.md contracts/
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepare-docs.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepare-docs.sh
new file mode 100644
index 000000000..d1317b092
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepare-docs.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+shopt -s globstar
+
+OUTDIR="$(node -p 'require("./docs/config.js").outputDir')"
+
+if [ ! -d node_modules ]; then
+ npm ci
+fi
+
+rm -rf "$OUTDIR"
+
+hardhat docgen
+
+# copy examples and adjust imports
+examples_source_dir="contracts/mocks/docs"
+examples_target_dir="docs/modules/api/examples"
+
+for f in "$examples_source_dir"/**/*.sol; do
+ name="${f/#"$examples_source_dir/"/}"
+ mkdir -p "$examples_target_dir/$(dirname "$name")"
+ sed -Ee '/^import/s|"(\.\./)+|"@openzeppelin/contracts/|' "$f" > "$examples_target_dir/$name"
+done
+
+node scripts/gen-nav.js "$OUTDIR" > "$OUTDIR/../nav.adoc"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepare.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepare.sh
new file mode 100644
index 000000000..a7d74227d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/prepare.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+if git status &>/dev/null; then git config core.hooksPath .githooks; fi
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/format-changelog.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/format-changelog.js
new file mode 100644
index 000000000..b8bcc8c71
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/format-changelog.js
@@ -0,0 +1,33 @@
+#!/usr/bin/env node
+
+// Adjusts the format of the changelog that changesets generates.
+// This is run automatically when npm version is run.
+
+const fs = require('fs');
+const changelog = fs.readFileSync('CHANGELOG.md', 'utf8');
+
+// Groups:
+// - 1: Pull Request Number and URL
+// - 2: Changeset entry
+const RELEASE_LINE_REGEX = /^- (\[#.*?\]\(.*?\))?.*?! - (.*)$/gm;
+
+// Captures vX.Y.Z or vX.Y.Z-rc.W
+const VERSION_TITLE_REGEX = /^## (\d+\.\d+\.\d+(-rc\.\d+)?)$/gm;
+
+const isPrerelease = process.env.PRERELEASE === 'true';
+
+const formatted = changelog
+ // Remove titles
+ .replace(/^### Major Changes\n\n/gm, '')
+ .replace(/^### Minor Changes\n\n/gm, '')
+ .replace(/^### Patch Changes\n\n/gm, '')
+ // Remove extra whitespace between items
+ .replace(/^(- \[.*\n)\n(?=-)/gm, '$1')
+ // Format each release line
+ .replace(RELEASE_LINE_REGEX, (_, pr, entry) => (pr ? `- ${entry} (${pr})` : `- ${entry}`))
+ // Add date to new version
+ .replace(VERSION_TITLE_REGEX, `\n## $1 (${new Date().toISOString().split('T')[0]})`)
+ // Conditionally allow vX.Y.Z.rc-.W sections only in prerelease
+ .replace(/^## \d\.\d\.\d-rc\S+[^]+?(?=^#)/gm, section => (isPrerelease ? section : ''));
+
+fs.writeFileSync('CHANGELOG.md', formatted);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/synchronize-versions.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/synchronize-versions.js
new file mode 100644
index 000000000..15aa25993
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/synchronize-versions.js
@@ -0,0 +1,15 @@
+#!/usr/bin/env node
+
+// Synchronizes the version in contracts/package.json with the one in package.json.
+// This is run automatically when npm version is run.
+
+const fs = require('fs');
+
+setVersion('package.json', 'contracts/package.json');
+
+function setVersion(from, to) {
+ const fromJson = JSON.parse(fs.readFileSync(from));
+ const toJson = JSON.parse(fs.readFileSync(to));
+ toJson.version = fromJson.version;
+ fs.writeFileSync(to, JSON.stringify(toJson, null, 2) + '\n');
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/update-comment.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/update-comment.js
new file mode 100644
index 000000000..9d6df2694
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/update-comment.js
@@ -0,0 +1,34 @@
+#!/usr/bin/env node
+const fs = require('fs');
+const proc = require('child_process');
+const semver = require('semver');
+const run = (cmd, ...args) => proc.execFileSync(cmd, args, { encoding: 'utf8' }).trim();
+
+const gitStatus = run('git', 'status', '--porcelain', '-uno', 'contracts/**/*.sol');
+if (gitStatus.length > 0) {
+ console.error('Contracts directory is not clean');
+ process.exit(1);
+}
+
+const { version } = require('../../package.json');
+
+// Get latest tag according to semver.
+const [tag] = run('git', 'tag')
+ .split(/\r?\n/)
+ .filter(semver.coerce) // check version can be processed
+ .filter(v => semver.satisfies(v, `< ${version}`)) // ignores prereleases unless currently a prerelease
+ .sort(semver.rcompare);
+
+// Ordering tag → HEAD is important here.
+const files = run('git', 'diff', tag, 'HEAD', '--name-only', 'contracts/**/*.sol')
+ .split(/\r?\n/)
+ .filter(file => file && !file.match(/mock/i) && fs.existsSync(file));
+
+for (const file of files) {
+ const current = fs.readFileSync(file, 'utf8');
+ const updated = current.replace(
+ /(\/\/ SPDX-License-Identifier:.*)$(\n\/\/ OpenZeppelin Contracts .*$)?/m,
+ `$1\n// OpenZeppelin Contracts (last updated v${version}) (${file.replace('contracts/', '')})`,
+ );
+ fs.writeFileSync(file, updated);
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/version.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/version.sh
new file mode 100644
index 000000000..7b0ddead3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/version.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+changeset version
+
+scripts/release/format-changelog.js
+scripts/release/synchronize-versions.js
+scripts/release/update-comment.js
+
+oz-docs update-version
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/exit-prerelease.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/exit-prerelease.sh
new file mode 100644
index 000000000..bcf9b9ae9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/exit-prerelease.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+npx changeset pre exit rc
+git add .
+git commit -m "Exit release candidate"
+git push origin
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/github-release.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/github-release.js
new file mode 100644
index 000000000..f213106b8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/github-release.js
@@ -0,0 +1,48 @@
+const { readFileSync } = require('fs');
+const { join } = require('path');
+const { version } = require(join(__dirname, '../../../package.json'));
+
+module.exports = async ({ github, context }) => {
+ const changelog = readFileSync('CHANGELOG.md', 'utf8');
+
+ await github.rest.repos.createRelease({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ tag_name: `v${version}`,
+ target_commitish: github.ref_name,
+ body: extractSection(changelog, version),
+ prerelease: process.env.PRERELEASE === 'true',
+ });
+};
+
+// From https://github.com/frangio/extract-changelog/blob/master/src/utils/word-regexp.ts
+function makeWordRegExp(word) {
+ const start = word.length > 0 && /\b/.test(word[0]) ? '\\b' : '';
+ const end = word.length > 0 && /\b/.test(word[word.length - 1]) ? '\\b' : '';
+ return new RegExp(start + [...word].map(c => (/[a-z0-9]/i.test(c) ? c : '\\' + c)).join('') + end);
+}
+
+// From https://github.com/frangio/extract-changelog/blob/master/src/core.ts
+function extractSection(document, wantedHeading) {
+ // ATX Headings as defined in GitHub Flavored Markdown (https://github.github.com/gfm/#atx-headings)
+ const heading = /^ {0,3}(?#{1,6})(?: [ \t\v\f]*(?.*?)[ \t\v\f]*)?(?:[\n\r]+|$)/gm;
+
+ const wantedHeadingRe = makeWordRegExp(wantedHeading);
+
+ let start, end;
+
+ for (const m of document.matchAll(heading)) {
+ if (!start) {
+ if (m.groups.text.search(wantedHeadingRe) === 0) {
+ start = m;
+ }
+ } else if (m.groups.lead.length <= start.groups.lead.length) {
+ end = m;
+ break;
+ }
+ }
+
+ if (start) {
+ return document.slice(start.index + start[0].length, end?.index);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/integrity-check.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/integrity-check.sh
new file mode 100644
index 000000000..86e99f929
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/integrity-check.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+CHECKSUMS="$RUNNER_TEMP/checksums.txt"
+
+# Extract tarball content into a tmp directory
+tar xf "$TARBALL" -C "$RUNNER_TEMP"
+
+# Move to extracted directory
+cd "$RUNNER_TEMP/package"
+
+# Checksum all Solidity files
+find . -type f -name "*.sol" | xargs shasum > "$CHECKSUMS"
+
+# Back to directory with git contents
+cd "$GITHUB_WORKSPACE/contracts"
+
+# Check against tarball contents
+shasum -c "$CHECKSUMS"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/pack.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/pack.sh
new file mode 100644
index 000000000..ce30712f8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/pack.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+dist_tag() {
+ PACKAGE_JSON_NAME="$(jq -r .name ./package.json)"
+ LATEST_NPM_VERSION="$(npm info "$PACKAGE_JSON_NAME" version)"
+ PACKAGE_JSON_VERSION="$(jq -r .version ./package.json)"
+
+ if [ "$PRERELEASE" = "true" ]; then
+ echo "next"
+ elif npx semver -r ">$LATEST_NPM_VERSION" "$PACKAGE_JSON_VERSION" > /dev/null; then
+ echo "latest"
+ else
+ # This is a patch for an older version
+ # npm can't publish without a tag
+ echo "tmp"
+ fi
+}
+
+cd contracts
+TARBALL="$(npm pack | tee /dev/stderr | tail -1)"
+echo "tarball_name=$TARBALL" >> $GITHUB_OUTPUT
+echo "tarball=$(pwd)/$TARBALL" >> $GITHUB_OUTPUT
+echo "tag=$(dist_tag)" >> $GITHUB_OUTPUT
+cd ..
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/publish.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/publish.sh
new file mode 100644
index 000000000..e490e5d00
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/publish.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+PACKAGE_JSON_NAME="$(tar xfO "$TARBALL" package/package.json | jq -r .name)"
+PACKAGE_JSON_VERSION="$(tar xfO "$TARBALL" package/package.json | jq -r .version)"
+
+# Intentionally escape $ to avoid interpolation and writing the token to disk
+echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" > .npmrc
+
+# Actual publish
+npm publish "$TARBALL" --tag "$TAG"
+
+# Clean up tags
+delete_tag() {
+ npm dist-tag rm "$PACKAGE_JSON_NAME" "$1"
+}
+
+if [ "$TAG" = tmp ]; then
+ delete_tag "$TAG"
+elif [ "$TAG" = latest ]; then
+ # Delete the next tag if it exists and is a prerelease for what is currently being published
+ if npm dist-tag ls "$PACKAGE_JSON_NAME" | grep -q "next: $PACKAGE_JSON_VERSION"; then
+ delete_tag next
+ fi
+fi
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/rerun.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/rerun.js
new file mode 100644
index 000000000..f48ce6ea2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/rerun.js
@@ -0,0 +1,7 @@
+module.exports = ({ github, context }) =>
+ github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ workflow_id: 'release-cycle.yml',
+ ref: process.env.REF || process.env.GITHUB_REF_NAME,
+ });
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/set-changesets-pr-title.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/set-changesets-pr-title.js
new file mode 100644
index 000000000..59b03b22a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/set-changesets-pr-title.js
@@ -0,0 +1,17 @@
+const { coerce, inc, rsort } = require('semver');
+const { join } = require('path');
+const { version } = require(join(__dirname, '../../../package.json'));
+
+module.exports = async ({ core }) => {
+ // Variables not in the context
+ const refName = process.env.GITHUB_REF_NAME;
+
+ // Compare package.json version's next patch vs. first version patch
+ // A recently opened branch will give the next patch for the previous minor
+ // So, we get the max against the patch 0 of the release branch's version
+ const branchPatch0 = coerce(refName.replace('release-v', '')).version;
+ const packageJsonNextPatch = inc(version, 'patch');
+ const [nextVersion] = rsort([branchPatch0, packageJsonNextPatch], false);
+
+ core.exportVariable('TITLE', `Release v${nextVersion}`);
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/start.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/start.sh
new file mode 100644
index 000000000..7683ec5bc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/start.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# Set changeset status location
+# This is needed because `changeset status --output` only works with relative routes
+CHANGESETS_STATUS_JSON="$(realpath --relative-to=. "$RUNNER_TEMP/status.json")"
+
+# Save changeset status to temp file
+npx changeset status --output="$CHANGESETS_STATUS_JSON"
+
+# Defensive assertion. SHOULD NOT BE REACHED
+if [ "$(jq '.releases | length' "$CHANGESETS_STATUS_JSON")" != 1 ]; then
+ echo "::error file=$CHANGESETS_STATUS_JSON::The status doesn't contain only 1 release"
+ exit 1;
+fi;
+
+# Create branch
+BRANCH_SUFFIX="$(jq -r '.releases[0].newVersion | gsub("\\.\\d+$"; "")' $CHANGESETS_STATUS_JSON)"
+RELEASE_BRANCH="release-v$BRANCH_SUFFIX"
+git checkout -b "$RELEASE_BRANCH"
+
+# Output branch
+echo "branch=$RELEASE_BRANCH" >> $GITHUB_OUTPUT
+
+# Enter in prerelease state
+npx changeset pre enter rc
+git add .
+git commit -m "Start release candidate"
+
+# Push branch
+if ! git push origin "$RELEASE_BRANCH"; then
+ echo "::error file=scripts/release/start.sh::Can't push $RELEASE_BRANCH. Did you forget to run this workflow from $RELEASE_BRANCH?"
+ exit 1
+fi
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/state.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/state.js
new file mode 100644
index 000000000..002f7774d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/release/workflow/state.js
@@ -0,0 +1,112 @@
+const { readPreState } = require('@changesets/pre');
+const { default: readChangesets } = require('@changesets/read');
+const { join } = require('path');
+const { fetch } = require('undici');
+const { version, name: packageName } = require(join(__dirname, '../../../contracts/package.json'));
+
+module.exports = async ({ github, context, core }) => {
+ const state = await getState({ github, context, core });
+
+ function setOutput(key, value) {
+ core.info(`State ${key} = ${value}`);
+ core.setOutput(key, value);
+ }
+
+ // Jobs to trigger
+ setOutput('start', shouldRunStart(state));
+ setOutput('promote', shouldRunPromote(state));
+ setOutput('changesets', shouldRunChangesets(state));
+ setOutput('publish', shouldRunPublish(state));
+ setOutput('merge', shouldRunMerge(state));
+
+ // Global Variables
+ setOutput('is_prerelease', state.prerelease);
+};
+
+function shouldRunStart({ isMaster, isWorkflowDispatch, botRun }) {
+ return isMaster && isWorkflowDispatch && !botRun;
+}
+
+function shouldRunPromote({ isReleaseBranch, isWorkflowDispatch, botRun }) {
+ return isReleaseBranch && isWorkflowDispatch && !botRun;
+}
+
+function shouldRunChangesets({ isReleaseBranch, isPush, isWorkflowDispatch, botRun }) {
+ return (isReleaseBranch && isPush) || (isReleaseBranch && isWorkflowDispatch && botRun);
+}
+
+function shouldRunPublish({ isReleaseBranch, isPush, hasPendingChangesets, isPublishedOnNpm }) {
+ return isReleaseBranch && isPush && !hasPendingChangesets && !isPublishedOnNpm;
+}
+
+function shouldRunMerge({
+ isReleaseBranch,
+ isPush,
+ prerelease,
+ isCurrentFinalVersion,
+ hasPendingChangesets,
+ prBackExists,
+}) {
+ return isReleaseBranch && isPush && !prerelease && isCurrentFinalVersion && !hasPendingChangesets && !prBackExists;
+}
+
+async function getState({ github, context, core }) {
+ // Variables not in the context
+ const refName = process.env.GITHUB_REF_NAME;
+ const botRun = process.env.TRIGGERING_ACTOR === 'github-actions[bot]';
+
+ const { changesets, preState } = await readChangesetState();
+
+ // Static vars
+ const state = {
+ refName,
+ hasPendingChangesets: changesets.length > 0,
+ prerelease: preState?.mode === 'pre',
+ isMaster: refName === 'master',
+ isReleaseBranch: refName.startsWith('release-v'),
+ isWorkflowDispatch: context.eventName === 'workflow_dispatch',
+ isPush: context.eventName === 'push',
+ isCurrentFinalVersion: !version.includes('-rc.'),
+ botRun,
+ };
+
+ // Async vars
+ const { data: prs } = await github.rest.pulls.list({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ head: `${context.repo.owner}:merge/${state.refName}`,
+ base: 'master',
+ state: 'open',
+ });
+
+ state.prBackExists = prs.length !== 0;
+
+ state.isPublishedOnNpm = await isPublishedOnNpm(packageName, version);
+
+ // Log every state value in debug mode
+ if (core.isDebug()) for (const [key, value] of Object.entries(state)) core.debug(`${key}: ${value}`);
+
+ return state;
+}
+
+// From https://github.com/changesets/action/blob/v1.4.1/src/readChangesetState.ts
+async function readChangesetState(cwd = process.cwd()) {
+ const preState = await readPreState(cwd);
+ const isInPreMode = preState !== undefined && preState.mode === 'pre';
+
+ let changesets = await readChangesets(cwd);
+
+ if (isInPreMode) {
+ changesets = changesets.filter(x => !preState.changesets.includes(x.id));
+ }
+
+ return {
+ preState: isInPreMode ? preState : undefined,
+ changesets,
+ };
+}
+
+async function isPublishedOnNpm(packageName, version) {
+ const res = await fetch(`https://registry.npmjs.com/${packageName}/${version}`);
+ return res.ok;
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/remove-ignored-artifacts.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/remove-ignored-artifacts.js
new file mode 100644
index 000000000..e156032b1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/remove-ignored-artifacts.js
@@ -0,0 +1,45 @@
+#!/usr/bin/env node
+
+// This script removes the build artifacts of ignored contracts.
+
+const fs = require('fs');
+const path = require('path');
+const match = require('micromatch');
+
+function readJSON(path) {
+ return JSON.parse(fs.readFileSync(path));
+}
+
+const pkgFiles = readJSON('package.json').files;
+
+// Get only negated patterns.
+const ignorePatterns = pkgFiles
+ .filter(pat => pat.startsWith('!'))
+ // Remove the negation part. Makes micromatch usage more intuitive.
+ .map(pat => pat.slice(1));
+
+const ignorePatternsSubtrees = ignorePatterns
+ // Add **/* to ignore all files contained in the directories.
+ .concat(ignorePatterns.map(pat => path.join(pat, '**/*')))
+ .map(p => p.replace(/^\//, ''));
+
+const artifactsDir = 'contracts/build/contracts';
+const buildinfo = 'artifacts/build-info';
+const filenames = fs.readdirSync(buildinfo);
+
+let n = 0;
+
+for (const filename of filenames) {
+ const solcOutput = readJSON(path.join(buildinfo, filename)).output;
+ for (const sourcePath in solcOutput.contracts) {
+ const ignore = match.any(sourcePath, ignorePatternsSubtrees);
+ if (ignore) {
+ for (const contract in solcOutput.contracts[sourcePath]) {
+ fs.unlinkSync(path.join(artifactsDir, contract + '.json'));
+ n += 1;
+ }
+ }
+ }
+}
+
+console.error(`Removed ${n} mock artifacts`);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/solhint-custom/index.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/solhint-custom/index.js
new file mode 100644
index 000000000..9625027ee
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/solhint-custom/index.js
@@ -0,0 +1,84 @@
+const path = require('path');
+const minimatch = require('minimatch');
+
+// Files matching these patterns will be ignored unless a rule has `static global = true`
+const ignore = ['contracts/mocks/**/*', 'test/**/*'];
+
+class Base {
+ constructor(reporter, config, source, fileName) {
+ this.reporter = reporter;
+ this.ignored = this.constructor.global || ignore.some(p => minimatch(path.normalize(fileName), p));
+ this.ruleId = this.constructor.ruleId;
+ if (this.ruleId === undefined) {
+ throw Error('missing ruleId static property');
+ }
+ }
+
+ error(node, message) {
+ if (!this.ignored) {
+ this.reporter.error(node, this.ruleId, message);
+ }
+ }
+}
+
+module.exports = [
+ class extends Base {
+ static ruleId = 'interface-names';
+
+ ContractDefinition(node) {
+ if (node.kind === 'interface' && !/^I[A-Z]/.test(node.name)) {
+ this.error(node, 'Interface names should have a capital I prefix');
+ }
+ }
+ },
+
+ class extends Base {
+ static ruleId = 'private-variables';
+
+ VariableDeclaration(node) {
+ const constantOrImmutable = node.isDeclaredConst || node.isImmutable;
+ if (node.isStateVar && !constantOrImmutable && node.visibility !== 'private') {
+ this.error(node, 'State variables must be private');
+ }
+ }
+ },
+
+ class extends Base {
+ static ruleId = 'leading-underscore';
+
+ VariableDeclaration(node) {
+ if (node.isDeclaredConst) {
+ // TODO: expand visibility and fix
+ if (node.visibility === 'private' && /^_/.test(node.name)) {
+ this.error(node, 'Constant variables should not have leading underscore');
+ }
+ } else if (node.visibility === 'private' && !/^_/.test(node.name)) {
+ this.error(node, 'Non-constant private variables must have leading underscore');
+ }
+ }
+
+ FunctionDefinition(node) {
+ if (node.visibility === 'private' || (node.visibility === 'internal' && node.parent.kind !== 'library')) {
+ if (!/^_/.test(node.name)) {
+ this.error(node, 'Private and internal functions must have leading underscore');
+ }
+ }
+ if (node.visibility === 'internal' && node.parent.kind === 'library') {
+ if (/^_/.test(node.name)) {
+ this.error(node, 'Library internal functions should not have leading underscore');
+ }
+ }
+ }
+ },
+
+ // TODO: re-enable and fix
+ // class extends Base {
+ // static ruleId = 'no-external-virtual';
+ //
+ // FunctionDefinition(node) {
+ // if (node.visibility == 'external' && node.isVirtual) {
+ // this.error(node, 'Functions should not be external and virtual');
+ // }
+ // }
+ // },
+];
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/solhint-custom/package.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/solhint-custom/package.json
new file mode 100644
index 000000000..075eb929d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/solhint-custom/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "solhint-plugin-openzeppelin",
+ "version": "0.0.0",
+ "private": true
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/update-docs-branch.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/update-docs-branch.js
new file mode 100644
index 000000000..cf61daad8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/update-docs-branch.js
@@ -0,0 +1,65 @@
+const proc = require('child_process');
+const read = cmd => proc.execSync(cmd, { encoding: 'utf8' }).trim();
+const run = cmd => {
+ proc.execSync(cmd, { stdio: 'inherit' });
+};
+const tryRead = cmd => {
+ try {
+ return read(cmd);
+ } catch {
+ return undefined;
+ }
+};
+
+const releaseBranchRegex = /^release-v(?(?\d+)\.(?\d+)(?:\.(?\d+))?)$/;
+
+const currentBranch = read('git rev-parse --abbrev-ref HEAD');
+const match = currentBranch.match(releaseBranchRegex);
+
+if (!match) {
+ console.error('Not currently on a release branch');
+ process.exit(1);
+}
+
+const pkgVersion = require('../package.json').version;
+
+if (pkgVersion.includes('-') && !pkgVersion.includes('.0.0-')) {
+ console.error('Refusing to update docs: non-major prerelease detected');
+ process.exit(0);
+}
+
+const current = match.groups;
+const docsBranch = `docs-v${current.major}.x`;
+
+// Fetch remotes and find the docs branch if it exists
+run('git fetch --all --no-tags');
+const matchingDocsBranches = tryRead(`git rev-parse --glob='*/${docsBranch}'`);
+
+if (!matchingDocsBranches) {
+ // Create the branch
+ run(`git checkout --orphan ${docsBranch}`);
+} else {
+ const [publishedRef, ...others] = new Set(matchingDocsBranches.split('\n'));
+ if (others.length > 0) {
+ console.error(
+ `Found conflicting ${docsBranch} branches.\n` +
+ 'Either local branch is outdated or there are multiple matching remote branches.',
+ );
+ process.exit(1);
+ }
+ const publishedVersion = JSON.parse(read(`git show ${publishedRef}:package.json`)).version;
+ const publishedMinor = publishedVersion.match(/\d+\.(?\d+)\.\d+/).groups.minor;
+ if (current.minor < publishedMinor) {
+ console.error('Refusing to update docs: newer version is published');
+ process.exit(0);
+ }
+
+ run('git checkout --quiet --detach');
+ run(`git reset --soft ${publishedRef}`);
+ run(`git checkout ${docsBranch}`);
+}
+
+run('npm run prepare-docs');
+run('git add -f docs'); // --force needed because generated docs files are gitignored
+run('git commit -m "Update docs"');
+run(`git checkout ${currentBranch}`);
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/README.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/README.md
new file mode 100644
index 000000000..2309f9e10
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/README.md
@@ -0,0 +1,21 @@
+The upgradeable variant of OpenZeppelin Contracts is automatically generated from the original Solidity code. We call this process "transpilation" and it is implemented by our [Upgradeability Transpiler](https://github.com/OpenZeppelin/openzeppelin-transpiler/).
+
+When the `master` branch or `release-v*` branches are updated, the code is transpiled and pushed to [OpenZeppelin/openzeppelin-contracts-upgradeable](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable) by the `upgradeable.yml` workflow.
+
+## `transpile.sh`
+
+Applies patches and invokes the transpiler with the command line flags we need for our requirements (for example, excluding certain files).
+
+## `transpile-onto.sh`
+
+```
+bash scripts/upgradeable/transpile-onto.sh [ ]
+```
+
+Transpiles the contents of the current git branch and commits the result as a new commit on branch ``. If branch `` doesn't exist, it will copy the commit history of `[ ]` (this is used in GitHub Actions, but is usually not necessary locally).
+
+## `patch-apply.sh` & `patch-save.sh`
+
+Some of the upgradeable contract variants require ad-hoc changes that are not implemented by the transpiler. These changes are implemented by patches stored in `upgradeable.patch` in this directory. `patch-apply.sh` applies these patches.
+
+If the patches fail to apply due to changes in the repo, the conflicts have to be resolved manually. Once fixed, `patch-save.sh` will take the changes staged in Git and update `upgradeable.patch` to match.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/patch-apply.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/patch-apply.sh
new file mode 100644
index 000000000..d9e17589b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/patch-apply.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+DIRNAME="$(dirname -- "${BASH_SOURCE[0]}")"
+PATCH="$DIRNAME/upgradeable.patch"
+
+error() {
+ echo Error: "$*" >&2
+ exit 1
+}
+
+if ! git diff-files --quiet ":!$PATCH" || ! git diff-index --quiet HEAD ":!$PATCH"; then
+ error "Repository must have no staged or unstaged changes"
+fi
+
+if ! git apply -3 "$PATCH"; then
+ error "Fix conflicts and run $DIRNAME/patch-save.sh"
+fi
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/patch-save.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/patch-save.sh
new file mode 100644
index 000000000..111e6f157
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/patch-save.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+DIRNAME="$(dirname -- "${BASH_SOURCE[0]}")"
+PATCH="$DIRNAME/upgradeable.patch"
+
+error() {
+ echo Error: "$*" >&2
+ exit 1
+}
+
+if ! git diff-files --quiet ":!$PATCH"; then
+ error "Unstaged changes. Stage to include in patch or temporarily stash."
+fi
+
+git diff-index --cached --patch --output="$PATCH" HEAD
+git restore --staged --worktree ":!$PATCH"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/transpile-onto.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/transpile-onto.sh
new file mode 100644
index 000000000..b8508f0c2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/transpile-onto.sh
@@ -0,0 +1,54 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+if [ $# -lt 1 ]; then
+ echo "usage: bash $0 [ ]" >&2
+ exit 1
+fi
+
+set -x
+
+target="$1"
+base="${2-}"
+
+bash scripts/upgradeable/transpile.sh
+
+commit="$(git rev-parse --short HEAD)"
+start_branch="$(git rev-parse --abbrev-ref HEAD)"
+
+git add contracts
+
+# detach from the current branch to avoid making changes to it
+git checkout --quiet --detach
+
+# switch to the target branch, creating it if necessary
+if git rev-parse -q --verify "$target"; then
+ # if the branch exists, make it the current HEAD without checking out its contents
+ git reset --soft "$target"
+ git checkout "$target"
+else
+ # if the branch doesn't exist, create it as an orphan and check it out
+ git checkout --orphan "$target"
+ if [ -n "$base" ] && git rev-parse -q --verify "$base"; then
+ # if base was specified and it exists, set it as the branch history
+ git reset --soft "$base"
+ fi
+fi
+
+# abort if there are no changes to commit at this point
+if git diff --quiet --cached; then
+ exit
+fi
+
+if [[ -v SUBMODULE_REMOTE ]]; then
+ lib=lib/openzeppelin-contracts
+ git submodule add -b "${base#origin/}" "$SUBMODULE_REMOTE" "$lib"
+ git -C "$lib" checkout "$commit"
+ git add "$lib"
+fi
+
+git commit -m "Transpile $commit"
+
+# return to original branch
+git checkout "$start_branch"
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/transpile.sh b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/transpile.sh
new file mode 100644
index 000000000..f7c848c13
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/transpile.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+
+set -euo pipefail -x
+
+VERSION="$(jq -r .version contracts/package.json)"
+DIRNAME="$(dirname -- "${BASH_SOURCE[0]}")"
+
+bash "$DIRNAME/patch-apply.sh"
+sed -i'' -e "s//$VERSION/g" "contracts/package.json"
+git add contracts/package.json
+
+npm run clean
+npm run compile
+
+build_info=($(jq -r '.input.sources | keys | if any(test("^contracts/mocks/.*\\bunreachable\\b")) then empty else input_filename end' artifacts/build-info/*))
+build_info_num=${#build_info[@]}
+
+if [ $build_info_num -ne 1 ]; then
+ echo "found $build_info_num relevant build info files but expected just 1"
+ exit 1
+fi
+
+# -D: delete original and excluded files
+# -b: use this build info file
+# -i: use included Initializable
+# -x: exclude proxy-related contracts with a few exceptions
+# -p: emit public initializer
+# -n: use namespaces
+# -N: exclude from namespaces transformation
+# -q: partial transpilation using @openzeppelin/contracts as peer project
+npx @openzeppelin/upgrade-safe-transpiler -D \
+ -b "$build_info" \
+ -i contracts/proxy/utils/Initializable.sol \
+ -x 'contracts-exposed/**/*' \
+ -x 'contracts/proxy/**/*' \
+ -x '!contracts/proxy/Clones.sol' \
+ -x '!contracts/proxy/ERC1967/ERC1967Storage.sol' \
+ -x '!contracts/proxy/ERC1967/ERC1967Utils.sol' \
+ -x '!contracts/proxy/utils/UUPSUpgradeable.sol' \
+ -x '!contracts/proxy/beacon/IBeacon.sol' \
+ -p 'contracts/access/manager/AccessManager.sol' \
+ -p 'contracts/finance/VestingWallet.sol' \
+ -p 'contracts/governance/TimelockController.sol' \
+ -p 'contracts/metatx/ERC2771Forwarder.sol' \
+ -n \
+ -N 'contracts/mocks/**/*' \
+ -q '@openzeppelin/'
+
+# delete compilation artifacts of vanilla code
+npm run clean
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/upgradeable.patch b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/upgradeable.patch
new file mode 100644
index 000000000..458ecd435
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/scripts/upgradeable/upgradeable.patch
@@ -0,0 +1,361 @@
+diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
+deleted file mode 100644
+index 35ad097ff..000000000
+--- a/.github/ISSUE_TEMPLATE/bug_report.md
++++ /dev/null
+@@ -1,21 +0,0 @@
+----
+-name: Bug report
+-about: Report a bug in OpenZeppelin Contracts
+-
+----
+-
+-
+-
+-
+-
+-**💻 Environment**
+-
+-
+-
+-**📝 Details**
+-
+-
+-
+-**🔢 Code to reproduce bug**
+-
+-
+diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
+index 4018cef29..d343a53d8 100644
+--- a/.github/ISSUE_TEMPLATE/config.yml
++++ b/.github/ISSUE_TEMPLATE/config.yml
+@@ -1,4 +1,8 @@
++blank_issues_enabled: false
+ contact_links:
++ - name: Bug Reports & Feature Requests
++ url: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/new/choose
++ about: Visit the OpenZeppelin Contracts repository
+ - name: Questions & Support Requests
+ url: https://forum.openzeppelin.com/c/support/contracts/18
+ about: Ask in the OpenZeppelin Forum
+diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
+deleted file mode 100644
+index ff596b0c3..000000000
+--- a/.github/ISSUE_TEMPLATE/feature_request.md
++++ /dev/null
+@@ -1,14 +0,0 @@
+----
+-name: Feature request
+-about: Suggest an idea for OpenZeppelin Contracts
+-
+----
+-
+-**🧐 Motivation**
+-
+-
+-**📝 Details**
+-
+-
+-
+-
+diff --git a/README.md b/README.md
+index fa7b4e31e..4799b6376 100644
+--- a/README.md
++++ b/README.md
+@@ -19,6 +19,9 @@
+ > [!IMPORTANT]
+ > OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. For upgradeable contracts, the storage layout of different major versions should be assumed incompatible, for example, it is unsafe to upgrade from 4.9.3 to 5.0.0. Learn more at [Backwards Compatibility](https://docs.openzeppelin.com/contracts/backwards-compatibility).
+
+++> [!NOTE]
+++> You are looking at the upgradeable variant of OpenZeppelin Contracts. Be sure to review the documentation on [Using OpenZeppelin Contracts with Upgrades](https://docs.openzeppelin.com/contracts/upgradeable).
+++
+ ## Overview
+
+ ### Installation
+@@ -26,7 +29,7 @@
+ #### Hardhat (npm)
+
+ ```
+-$ npm install @openzeppelin/contracts
++$ npm install @openzeppelin/contracts-upgradeable
+ ```
+
+ #### Foundry (git)
+@@ -38,10 +41,10 @@ $ npm install @openzeppelin/contracts
+ > Foundry installs the latest version initially, but subsequent `forge update` commands will use the `master` branch.
+
+ ```
+-$ forge install OpenZeppelin/openzeppelin-contracts
++$ forge install OpenZeppelin/openzeppelin-contracts-upgradeable
+ ```
+
+-Add `@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/` in `remappings.txt.`
++Add `@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/` in `remappings.txt.`
+
+ ### Usage
+
+@@ -50,10 +53,11 @@ Once installed, you can use the contracts in the library by importing them:
+ ```solidity
+ pragma solidity ^0.8.20;
+
+-import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
++import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
+
+-contract MyCollectible is ERC721 {
+- constructor() ERC721("MyCollectible", "MCO") {
++contract MyCollectible is ERC721Upgradeable {
++ function initialize() initializer public {
++ __ERC721_init("MyCollectible", "MCO");
+ }
+ }
+ ```
+diff --git a/contracts/package.json b/contracts/package.json
+index 845e8c403..8dc181b91 100644
+--- a/contracts/package.json
++++ b/contracts/package.json
+@@ -1,5 +1,5 @@
+ {
+- "name": "@openzeppelin/contracts",
++ "name": "@openzeppelin/contracts-upgradeable",
+ "description": "Secure Smart Contract library for Solidity",
+ "version": "5.0.2",
+ "files": [
+@@ -13,7 +13,7 @@
+ },
+ "repository": {
+ "type": "git",
+- "url": "https://github.com/OpenZeppelin/openzeppelin-contracts.git"
++ "url": "https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable.git"
+ },
+ "keywords": [
+ "solidity",
+@@ -28,5 +28,8 @@
+ "bugs": {
+ "url": "https://github.com/OpenZeppelin/openzeppelin-contracts/issues"
+ },
+- "homepage": "https://openzeppelin.com/contracts/"
++ "homepage": "https://openzeppelin.com/contracts/",
++ "peerDependencies": {
++ "@openzeppelin/contracts": ""
++ }
+ }
+diff --git a/contracts/utils/cryptography/EIP712.sol b/contracts/utils/cryptography/EIP712.sol
+index 77c4c8990..602467f40 100644
+--- a/contracts/utils/cryptography/EIP712.sol
++++ b/contracts/utils/cryptography/EIP712.sol
+@@ -4,7 +4,6 @@
+ pragma solidity ^0.8.20;
+
+ import {MessageHashUtils} from "./MessageHashUtils.sol";
+-import {ShortStrings, ShortString} from "../ShortStrings.sol";
+ import {IERC5267} from "../../interfaces/IERC5267.sol";
+
+ /**
+@@ -28,28 +27,18 @@ import {IERC5267} from "../../interfaces/IERC5267.sol";
+ * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
+ * separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
+ * separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
+- *
+- * @custom:oz-upgrades-unsafe-allow state-variable-immutable
+ */
+ abstract contract EIP712 is IERC5267 {
+- using ShortStrings for *;
+-
+ bytes32 private constant TYPE_HASH =
+ keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
+
+- // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
+- // invalidate the cached domain separator if the chain id changes.
+- bytes32 private immutable _cachedDomainSeparator;
+- uint256 private immutable _cachedChainId;
+- address private immutable _cachedThis;
+-
++ /// @custom:oz-renamed-from _HASHED_NAME
+ bytes32 private immutable _hashedName;
++ /// @custom:oz-renamed-from _HASHED_VERSION
+ bytes32 private immutable _hashedVersion;
+
+- ShortString private immutable _name;
+- ShortString private immutable _version;
+- string private _nameFallback;
+- string private _versionFallback;
++ string private _name;
++ string private _version;
+
+ /**
+ * @dev Initializes the domain separator and parameter caches.
+@@ -64,29 +53,23 @@ abstract contract EIP712 is IERC5267 {
+ * contract upgrade].
+ */
+ constructor(string memory name, string memory version) {
+- _name = name.toShortStringWithFallback(_nameFallback);
+- _version = version.toShortStringWithFallback(_versionFallback);
+- _hashedName = keccak256(bytes(name));
+- _hashedVersion = keccak256(bytes(version));
+-
+- _cachedChainId = block.chainid;
+- _cachedDomainSeparator = _buildDomainSeparator();
+- _cachedThis = address(this);
++ _name = name;
++ _version = version;
++
++ // Reset prior values in storage if upgrading
++ _hashedName = 0;
++ _hashedVersion = 0;
+ }
+
+ /**
+ * @dev Returns the domain separator for the current chain.
+ */
+ function _domainSeparatorV4() internal view returns (bytes32) {
+- if (address(this) == _cachedThis && block.chainid == _cachedChainId) {
+- return _cachedDomainSeparator;
+- } else {
+- return _buildDomainSeparator();
+- }
++ return _buildDomainSeparator();
+ }
+
+ function _buildDomainSeparator() private view returns (bytes32) {
+- return keccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
++ return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this)));
+ }
+
+ /**
+@@ -125,6 +108,10 @@ abstract contract EIP712 is IERC5267 {
+ uint256[] memory extensions
+ )
+ {
++ // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized
++ // and the EIP712 domain is not reliable, as it will be missing name and version.
++ require(_hashedName == 0 && _hashedVersion == 0, "EIP712: Uninitialized");
++
+ return (
+ hex"0f", // 01111
+ _EIP712Name(),
+@@ -139,22 +126,62 @@ abstract contract EIP712 is IERC5267 {
+ /**
+ * @dev The name parameter for the EIP712 domain.
+ *
+- * NOTE: By default this function reads _name which is an immutable value.
+- * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
++ * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
++ * are a concern.
+ */
+- // solhint-disable-next-line func-name-mixedcase
+- function _EIP712Name() internal view returns (string memory) {
+- return _name.toStringWithFallback(_nameFallback);
++ function _EIP712Name() internal view virtual returns (string memory) {
++ return _name;
+ }
+
+ /**
+ * @dev The version parameter for the EIP712 domain.
+ *
+- * NOTE: By default this function reads _version which is an immutable value.
+- * It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
++ * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs
++ * are a concern.
+ */
+- // solhint-disable-next-line func-name-mixedcase
+- function _EIP712Version() internal view returns (string memory) {
+- return _version.toStringWithFallback(_versionFallback);
++ function _EIP712Version() internal view virtual returns (string memory) {
++ return _version;
++ }
++
++ /**
++ * @dev The hash of the name parameter for the EIP712 domain.
++ *
++ * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead.
++ */
++ function _EIP712NameHash() internal view returns (bytes32) {
++ string memory name = _EIP712Name();
++ if (bytes(name).length > 0) {
++ return keccak256(bytes(name));
++ } else {
++ // If the name is empty, the contract may have been upgraded without initializing the new storage.
++ // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design.
++ bytes32 hashedName = _hashedName;
++ if (hashedName != 0) {
++ return hashedName;
++ } else {
++ return keccak256("");
++ }
++ }
++ }
++
++ /**
++ * @dev The hash of the version parameter for the EIP712 domain.
++ *
++ * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead.
++ */
++ function _EIP712VersionHash() internal view returns (bytes32) {
++ string memory version = _EIP712Version();
++ if (bytes(version).length > 0) {
++ return keccak256(bytes(version));
++ } else {
++ // If the version is empty, the contract may have been upgraded without initializing the new storage.
++ // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design.
++ bytes32 hashedVersion = _hashedVersion;
++ if (hashedVersion != 0) {
++ return hashedVersion;
++ } else {
++ return keccak256("");
++ }
++ }
+ }
+ }
+diff --git a/package.json b/package.json
+index c4b358e10..96ab2559c 100644
+--- a/package.json
++++ b/package.json
+@@ -32,7 +32,7 @@
+ },
+ "repository": {
+ "type": "git",
+- "url": "https://github.com/OpenZeppelin/openzeppelin-contracts.git"
++ "url": "https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable.git"
+ },
+ "keywords": [
+ "solidity",
+diff --git a/remappings.txt b/remappings.txt
+index 304d1386a..a1cd63bee 100644
+--- a/remappings.txt
++++ b/remappings.txt
+@@ -1 +1,2 @@
+-@openzeppelin/contracts/=contracts/
++@openzeppelin/contracts-upgradeable/=contracts/
++@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
+diff --git a/test/utils/cryptography/EIP712.test.js b/test/utils/cryptography/EIP712.test.js
+index 2b6e7fa97..268e0d29d 100644
+--- a/test/utils/cryptography/EIP712.test.js
++++ b/test/utils/cryptography/EIP712.test.js
+@@ -47,27 +47,6 @@ describe('EIP712', function () {
+ const rebuildDomain = await getDomain(this.eip712);
+ expect(rebuildDomain).to.be.deep.equal(this.domain);
+ });
+-
+- if (shortOrLong === 'short') {
+- // Long strings are in storage, and the proxy will not be properly initialized unless
+- // the upgradeable contract variant is used and the initializer is invoked.
+-
+- it('adjusts when behind proxy', async function () {
+- const factory = await ethers.deployContract('$Clones');
+-
+- const clone = await factory
+- .$clone(this.eip712)
+- .then(tx => tx.wait())
+- .then(receipt => receipt.logs.find(ev => ev.fragment.name == 'return$clone_address').args.instance)
+- .then(address => ethers.getContractAt('$EIP712Verifier', address));
+-
+- const expectedDomain = { ...this.domain, verifyingContract: clone.target };
+- expect(await getDomain(clone)).to.be.deep.equal(expectedDomain);
+-
+- const expectedSeparator = await domainSeparator(expectedDomain);
+- expect(await clone.$_domainSeparatorV4()).to.equal(expectedSeparator);
+- });
+- }
+ });
+
+ it('hash digest', async function () {
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/slither.config.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/slither.config.json
new file mode 100644
index 000000000..fa52f4dd1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/slither.config.json
@@ -0,0 +1,5 @@
+{
+ "detectors_to_run": "arbitrary-send-erc20,array-by-reference,incorrect-shift,name-reused,rtlo,suicidal,uninitialized-state,uninitialized-storage,arbitrary-send-erc20-permit,controlled-array-length,controlled-delegatecall,delegatecall-loop,msg-value-loop,reentrancy-eth,unchecked-transfer,weak-prng,domain-separator-collision,erc20-interface,erc721-interface,locked-ether,mapping-deletion,shadowing-abstract,tautology,write-after-write,boolean-cst,reentrancy-no-eth,reused-constructor,tx-origin,unchecked-lowlevel,unchecked-send,variable-scope,void-cst,events-access,events-maths,incorrect-unary,boolean-equal,cyclomatic-complexity,deprecated-standards,erc20-indexed,function-init-state,pragma,unused-state,reentrancy-unlimited-gas,constable-states,immutable-states,var-read-using-this",
+ "filter_paths": "contracts/mocks,contracts/vendor,contracts-exposed",
+ "compile_force_framework": "hardhat"
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/solhint.config.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/solhint.config.js
new file mode 100644
index 000000000..f0bd7994f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/solhint.config.js
@@ -0,0 +1,26 @@
+const customRules = require('./scripts/solhint-custom');
+
+const rules = [
+ 'avoid-tx-origin',
+ 'const-name-snakecase',
+ 'contract-name-camelcase',
+ 'event-name-camelcase',
+ 'explicit-types',
+ 'func-name-mixedcase',
+ 'func-param-name-mixedcase',
+ 'imports-on-top',
+ 'modifier-name-mixedcase',
+ 'no-console',
+ 'no-global-import',
+ 'no-unused-vars',
+ 'quotes',
+ 'use-forbidden-name',
+ 'var-name-mixedcase',
+ 'visibility-modifier-order',
+ ...customRules.map(r => `openzeppelin/${r.ruleId}`),
+];
+
+module.exports = {
+ plugins: ['openzeppelin'],
+ rules: Object.fromEntries(rules.map(r => [r, 'error'])),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/TESTING.md b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/TESTING.md
new file mode 100644
index 000000000..a5ee9323f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/TESTING.md
@@ -0,0 +1,3 @@
+## Testing
+
+Unit test are critical to OpenZeppelin Contracts. They help ensure code quality and mitigate against security vulnerabilities. The directory structure within the `/test` directory corresponds to the `/contracts` directory.
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/AccessControl.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/AccessControl.behavior.js
new file mode 100644
index 000000000..b7ae2a950
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/AccessControl.behavior.js
@@ -0,0 +1,874 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+const time = require('../helpers/time');
+
+const { shouldSupportInterfaces } = require('../utils/introspection/SupportsInterface.behavior');
+
+const DEFAULT_ADMIN_ROLE = ethers.ZeroHash;
+const ROLE = ethers.id('ROLE');
+const OTHER_ROLE = ethers.id('OTHER_ROLE');
+
+function shouldBehaveLikeAccessControl() {
+ beforeEach(async function () {
+ [this.authorized, this.other, this.otherAdmin] = this.accounts;
+ });
+
+ shouldSupportInterfaces(['AccessControl']);
+
+ describe('default admin', function () {
+ it('deployer has default admin role', async function () {
+ expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin)).to.be.true;
+ });
+
+ it("other roles's admin is the default admin role", async function () {
+ expect(await this.mock.getRoleAdmin(ROLE)).to.equal(DEFAULT_ADMIN_ROLE);
+ });
+
+ it("default admin role's admin is itself", async function () {
+ expect(await this.mock.getRoleAdmin(DEFAULT_ADMIN_ROLE)).to.equal(DEFAULT_ADMIN_ROLE);
+ });
+ });
+
+ describe('granting', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized);
+ });
+
+ it('non-admin cannot grant role to other accounts', async function () {
+ await expect(this.mock.connect(this.other).grantRole(ROLE, this.authorized))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, DEFAULT_ADMIN_ROLE);
+ });
+
+ it('accounts can be granted a role multiple times', async function () {
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized);
+ await expect(this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized)).to.not.emit(
+ this.mock,
+ 'RoleGranted',
+ );
+ });
+ });
+
+ describe('revoking', function () {
+ it('roles that are not had can be revoked', async function () {
+ expect(await this.mock.hasRole(ROLE, this.authorized)).to.be.false;
+
+ await expect(this.mock.connect(this.defaultAdmin).revokeRole(ROLE, this.authorized)).to.not.emit(
+ this.mock,
+ 'RoleRevoked',
+ );
+ });
+
+ describe('with granted role', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized);
+ });
+
+ it('admin can revoke role', async function () {
+ await expect(this.mock.connect(this.defaultAdmin).revokeRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'RoleRevoked')
+ .withArgs(ROLE, this.authorized, this.defaultAdmin);
+
+ expect(await this.mock.hasRole(ROLE, this.authorized)).to.be.false;
+ });
+
+ it('non-admin cannot revoke role', async function () {
+ await expect(this.mock.connect(this.other).revokeRole(ROLE, this.authorized))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, DEFAULT_ADMIN_ROLE);
+ });
+
+ it('a role can be revoked multiple times', async function () {
+ await this.mock.connect(this.defaultAdmin).revokeRole(ROLE, this.authorized);
+
+ await expect(this.mock.connect(this.defaultAdmin).revokeRole(ROLE, this.authorized)).to.not.emit(
+ this.mock,
+ 'RoleRevoked',
+ );
+ });
+ });
+ });
+
+ describe('renouncing', function () {
+ it('roles that are not had can be renounced', async function () {
+ await expect(this.mock.connect(this.authorized).renounceRole(ROLE, this.authorized)).to.not.emit(
+ this.mock,
+ 'RoleRevoked',
+ );
+ });
+
+ describe('with granted role', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized);
+ });
+
+ it('bearer can renounce role', async function () {
+ await expect(this.mock.connect(this.authorized).renounceRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'RoleRevoked')
+ .withArgs(ROLE, this.authorized, this.authorized);
+
+ expect(await this.mock.hasRole(ROLE, this.authorized)).to.be.false;
+ });
+
+ it('only the sender can renounce their roles', async function () {
+ await expect(
+ this.mock.connect(this.defaultAdmin).renounceRole(ROLE, this.authorized),
+ ).to.be.revertedWithCustomError(this.mock, 'AccessControlBadConfirmation');
+ });
+
+ it('a role can be renounced multiple times', async function () {
+ await this.mock.connect(this.authorized).renounceRole(ROLE, this.authorized);
+
+ await expect(this.mock.connect(this.authorized).renounceRole(ROLE, this.authorized)).not.to.emit(
+ this.mock,
+ 'RoleRevoked',
+ );
+ });
+ });
+ });
+
+ describe('setting role admin', function () {
+ beforeEach(async function () {
+ await expect(this.mock.$_setRoleAdmin(ROLE, OTHER_ROLE))
+ .to.emit(this.mock, 'RoleAdminChanged')
+ .withArgs(ROLE, DEFAULT_ADMIN_ROLE, OTHER_ROLE);
+
+ await this.mock.connect(this.defaultAdmin).grantRole(OTHER_ROLE, this.otherAdmin);
+ });
+
+ it("a role's admin role can be changed", async function () {
+ expect(await this.mock.getRoleAdmin(ROLE)).to.equal(OTHER_ROLE);
+ });
+
+ it('the new admin can grant roles', async function () {
+ await expect(this.mock.connect(this.otherAdmin).grantRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'RoleGranted')
+ .withArgs(ROLE, this.authorized, this.otherAdmin);
+ });
+
+ it('the new admin can revoke roles', async function () {
+ await this.mock.connect(this.otherAdmin).grantRole(ROLE, this.authorized);
+ await expect(this.mock.connect(this.otherAdmin).revokeRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'RoleRevoked')
+ .withArgs(ROLE, this.authorized, this.otherAdmin);
+ });
+
+ it("a role's previous admins no longer grant roles", async function () {
+ await expect(this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.defaultAdmin, OTHER_ROLE);
+ });
+
+ it("a role's previous admins no longer revoke roles", async function () {
+ await expect(this.mock.connect(this.defaultAdmin).revokeRole(ROLE, this.authorized))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.defaultAdmin, OTHER_ROLE);
+ });
+ });
+
+ describe('onlyRole modifier', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized);
+ });
+
+ it('do not revert if sender has role', async function () {
+ await this.mock.connect(this.authorized).$_checkRole(ROLE);
+ });
+
+ it("revert if sender doesn't have role #1", async function () {
+ await expect(this.mock.connect(this.other).$_checkRole(ROLE))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, ROLE);
+ });
+
+ it("revert if sender doesn't have role #2", async function () {
+ await expect(this.mock.connect(this.authorized).$_checkRole(OTHER_ROLE))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.authorized, OTHER_ROLE);
+ });
+ });
+
+ describe('internal functions', function () {
+ describe('_grantRole', function () {
+ it('return true if the account does not have the role', async function () {
+ await expect(this.mock.$_grantRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'return$_grantRole')
+ .withArgs(true);
+ });
+
+ it('return false if the account has the role', async function () {
+ await this.mock.$_grantRole(ROLE, this.authorized);
+
+ await expect(this.mock.$_grantRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'return$_grantRole')
+ .withArgs(false);
+ });
+ });
+
+ describe('_revokeRole', function () {
+ it('return true if the account has the role', async function () {
+ await this.mock.$_grantRole(ROLE, this.authorized);
+
+ await expect(this.mock.$_revokeRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'return$_revokeRole')
+ .withArgs(true);
+ });
+
+ it('return false if the account does not have the role', async function () {
+ await expect(this.mock.$_revokeRole(ROLE, this.authorized))
+ .to.emit(this.mock, 'return$_revokeRole')
+ .withArgs(false);
+ });
+ });
+ });
+}
+
+function shouldBehaveLikeAccessControlEnumerable() {
+ beforeEach(async function () {
+ [this.authorized, this.other, this.otherAdmin, this.otherAuthorized] = this.accounts;
+ });
+
+ shouldSupportInterfaces(['AccessControlEnumerable']);
+
+ describe('enumerating', function () {
+ it('role bearers can be enumerated', async function () {
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.authorized);
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.other);
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.otherAuthorized);
+ await this.mock.connect(this.defaultAdmin).revokeRole(ROLE, this.other);
+
+ const expectedMembers = [this.authorized.address, this.otherAuthorized.address];
+
+ const memberCount = await this.mock.getRoleMemberCount(ROLE);
+ const members = [];
+ for (let i = 0; i < memberCount; ++i) {
+ members.push(await this.mock.getRoleMember(ROLE, i));
+ }
+
+ expect(memberCount).to.equal(expectedMembers.length);
+ expect(members).to.deep.equal(expectedMembers);
+ expect(await this.mock.getRoleMembers(ROLE)).to.deep.equal(expectedMembers);
+ });
+
+ it('role enumeration should be in sync after renounceRole call', async function () {
+ expect(await this.mock.getRoleMemberCount(ROLE)).to.equal(0);
+ await this.mock.connect(this.defaultAdmin).grantRole(ROLE, this.defaultAdmin);
+ expect(await this.mock.getRoleMemberCount(ROLE)).to.equal(1);
+ await this.mock.connect(this.defaultAdmin).renounceRole(ROLE, this.defaultAdmin);
+ expect(await this.mock.getRoleMemberCount(ROLE)).to.equal(0);
+ });
+ });
+}
+
+function shouldBehaveLikeAccessControlDefaultAdminRules() {
+ shouldSupportInterfaces(['AccessControlDefaultAdminRules']);
+
+ beforeEach(async function () {
+ [this.newDefaultAdmin, this.other] = this.accounts;
+ });
+
+ for (const getter of ['owner', 'defaultAdmin']) {
+ describe(`${getter}()`, function () {
+ it('has a default set to the initial default admin', async function () {
+ const value = await this.mock[getter]();
+ expect(value).to.equal(this.defaultAdmin);
+ expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, value)).to.be.true;
+ });
+
+ it('changes if the default admin changes', async function () {
+ // Starts an admin transfer
+ await this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin);
+
+ // Wait for acceptance
+ await time.increaseBy.timestamp(this.delay + 1n, false);
+ await this.mock.connect(this.newDefaultAdmin).acceptDefaultAdminTransfer();
+
+ const value = await this.mock[getter]();
+ expect(value).to.equal(this.newDefaultAdmin);
+ });
+ });
+ }
+
+ describe('pendingDefaultAdmin()', function () {
+ it('returns 0 if no pending default admin transfer', async function () {
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(0);
+ });
+
+ describe('when there is a scheduled default admin transfer', function () {
+ beforeEach('begins admin transfer', async function () {
+ await this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin);
+ });
+
+ for (const [fromSchedule, tag] of [
+ [-1n, 'before'],
+ [0n, 'exactly when'],
+ [1n, 'after'],
+ ]) {
+ it(`returns pending admin and schedule ${tag} it passes if not accepted`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdmin();
+ await time.increaseTo.timestamp(firstSchedule + fromSchedule);
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(this.newDefaultAdmin);
+ expect(schedule).to.equal(firstSchedule);
+ });
+ }
+
+ it('returns 0 after schedule passes and the transfer was accepted', async function () {
+ // Wait after schedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdmin();
+ await time.increaseTo.timestamp(firstSchedule + 1n, false);
+
+ // Accepts
+ await this.mock.connect(this.newDefaultAdmin).acceptDefaultAdminTransfer();
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(0);
+ });
+ });
+ });
+
+ describe('defaultAdminDelay()', function () {
+ it('returns the current delay', async function () {
+ expect(await this.mock.defaultAdminDelay()).to.equal(this.delay);
+ });
+
+ describe('when there is a scheduled delay change', function () {
+ const newDelay = 0x1337n; // Any change
+
+ beforeEach('begins delay change', async function () {
+ await this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(newDelay);
+ });
+
+ for (const [fromSchedule, tag, expectNew, delayTag] of [
+ [-1n, 'before', false, 'old'],
+ [0n, 'exactly when', false, 'old'],
+ [1n, 'after', true, 'new'],
+ ]) {
+ it(`returns ${delayTag} delay ${tag} delay schedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule } = await this.mock.pendingDefaultAdminDelay();
+ await time.increaseTo.timestamp(schedule + fromSchedule);
+
+ const currentDelay = await this.mock.defaultAdminDelay();
+ expect(currentDelay).to.equal(expectNew ? newDelay : this.delay);
+ });
+ }
+ });
+ });
+
+ describe('pendingDefaultAdminDelay()', function () {
+ it('returns 0 if not set', async function () {
+ const { newDelay, schedule } = await this.mock.pendingDefaultAdminDelay();
+ expect(newDelay).to.equal(0);
+ expect(schedule).to.equal(0);
+ });
+
+ describe('when there is a scheduled delay change', function () {
+ const newDelay = 0x1337n; // Any change
+
+ beforeEach('begins admin transfer', async function () {
+ await this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(newDelay);
+ });
+
+ for (const [fromSchedule, tag, expectedDelay, delayTag, expectZeroSchedule] of [
+ [-1n, 'before', newDelay, 'new'],
+ [0n, 'exactly when', newDelay, 'new'],
+ [1n, 'after', 0, 'zero', true],
+ ]) {
+ it(`returns ${delayTag} delay ${tag} delay schedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdminDelay();
+ await time.increaseTo.timestamp(firstSchedule + fromSchedule);
+
+ const { newDelay, schedule } = await this.mock.pendingDefaultAdminDelay();
+ expect(newDelay).to.equal(expectedDelay);
+ expect(schedule).to.equal(expectZeroSchedule ? 0 : firstSchedule);
+ });
+ }
+ });
+ });
+
+ describe('defaultAdminDelayIncreaseWait()', function () {
+ it('should return 5 days (default)', async function () {
+ expect(await this.mock.defaultAdminDelayIncreaseWait()).to.equal(time.duration.days(5));
+ });
+ });
+
+ it('should revert if granting default admin role', async function () {
+ await expect(
+ this.mock.connect(this.defaultAdmin).grantRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin),
+ ).to.be.revertedWithCustomError(this.mock, 'AccessControlEnforcedDefaultAdminRules');
+ });
+
+ it('should revert if revoking default admin role', async function () {
+ await expect(
+ this.mock.connect(this.defaultAdmin).revokeRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin),
+ ).to.be.revertedWithCustomError(this.mock, 'AccessControlEnforcedDefaultAdminRules');
+ });
+
+ it("should revert if defaultAdmin's admin is changed", async function () {
+ await expect(this.mock.$_setRoleAdmin(DEFAULT_ADMIN_ROLE, OTHER_ROLE)).to.be.revertedWithCustomError(
+ this.mock,
+ 'AccessControlEnforcedDefaultAdminRules',
+ );
+ });
+
+ it('should not grant the default admin role twice', async function () {
+ await expect(this.mock.$_grantRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin)).to.be.revertedWithCustomError(
+ this.mock,
+ 'AccessControlEnforcedDefaultAdminRules',
+ );
+ });
+
+ describe('begins a default admin transfer', function () {
+ it('reverts if called by non default admin accounts', async function () {
+ await expect(this.mock.connect(this.other).beginDefaultAdminTransfer(this.newDefaultAdmin))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, DEFAULT_ADMIN_ROLE);
+ });
+
+ describe('when there is no pending delay nor pending admin transfer', function () {
+ it('should set pending default admin and schedule', async function () {
+ const nextBlockTimestamp = (await time.clock.timestamp()) + 1n;
+ const acceptSchedule = nextBlockTimestamp + this.delay;
+
+ await time.increaseTo.timestamp(nextBlockTimestamp, false); // set timestamp but don't mine the block yet
+ await expect(this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin))
+ .to.emit(this.mock, 'DefaultAdminTransferScheduled')
+ .withArgs(this.newDefaultAdmin, acceptSchedule);
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(this.newDefaultAdmin);
+ expect(schedule).to.equal(acceptSchedule);
+ });
+ });
+
+ describe('when there is a pending admin transfer', function () {
+ beforeEach('sets a pending default admin transfer', async function () {
+ await this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin);
+ this.acceptSchedule = (await time.clock.timestamp()) + this.delay;
+ });
+
+ for (const [fromSchedule, tag] of [
+ [-1n, 'before'],
+ [0n, 'exactly when'],
+ [1n, 'after'],
+ ]) {
+ it(`should be able to begin a transfer again ${tag} acceptSchedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ await time.increaseTo.timestamp(this.acceptSchedule + fromSchedule, false);
+
+ // defaultAdmin changes its mind and begin again to another address
+ await expect(this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.other)).to.emit(
+ this.mock,
+ 'DefaultAdminTransferCanceled', // Cancellation is always emitted since it was never accepted
+ );
+ const newSchedule = (await time.clock.timestamp()) + this.delay;
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(this.other);
+ expect(schedule).to.equal(newSchedule);
+ });
+ }
+
+ it('should not emit a cancellation event if the new default admin accepted', async function () {
+ // Wait until the acceptSchedule has passed
+ await time.increaseTo.timestamp(this.acceptSchedule + 1n, false);
+
+ // Accept and restart
+ await this.mock.connect(this.newDefaultAdmin).acceptDefaultAdminTransfer();
+ await expect(this.mock.connect(this.newDefaultAdmin).beginDefaultAdminTransfer(this.other)).to.not.emit(
+ this.mock,
+ 'DefaultAdminTransferCanceled',
+ );
+ });
+ });
+
+ describe('when there is a pending delay', function () {
+ const newDelay = time.duration.hours(3);
+
+ beforeEach('schedule a delay change', async function () {
+ await this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(newDelay);
+ ({ schedule: this.effectSchedule } = await this.mock.pendingDefaultAdminDelay());
+ });
+
+ for (const [fromSchedule, schedulePassed, expectNewDelay] of [
+ [-1n, 'before', false],
+ [0n, 'exactly when', false],
+ [1n, 'after', true],
+ ]) {
+ it(`should set the ${
+ expectNewDelay ? 'new' : 'old'
+ } delay and apply it to next default admin transfer schedule ${schedulePassed} effectSchedule passed`, async function () {
+ // Wait until the expected fromSchedule time
+ const nextBlockTimestamp = this.effectSchedule + fromSchedule;
+ await time.increaseTo.timestamp(nextBlockTimestamp, false);
+
+ // Start the new default admin transfer and get its schedule
+ const expectedDelay = expectNewDelay ? newDelay : this.delay;
+ const expectedAcceptSchedule = nextBlockTimestamp + expectedDelay;
+ await expect(this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin))
+ .to.emit(this.mock, 'DefaultAdminTransferScheduled')
+ .withArgs(this.newDefaultAdmin, expectedAcceptSchedule);
+
+ // Check that the schedule corresponds with the new delay
+ const { newAdmin, schedule: transferSchedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(this.newDefaultAdmin);
+ expect(transferSchedule).to.equal(expectedAcceptSchedule);
+ });
+ }
+ });
+ });
+
+ describe('accepts transfer admin', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin);
+ this.acceptSchedule = (await time.clock.timestamp()) + this.delay;
+ });
+
+ it('should revert if caller is not pending default admin', async function () {
+ await time.increaseTo.timestamp(this.acceptSchedule + 1n, false);
+ await expect(this.mock.connect(this.other).acceptDefaultAdminTransfer())
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlInvalidDefaultAdmin')
+ .withArgs(this.other);
+ });
+
+ describe('when caller is pending default admin and delay has passed', function () {
+ beforeEach(async function () {
+ await time.increaseTo.timestamp(this.acceptSchedule + 1n, false);
+ });
+
+ it('accepts a transfer and changes default admin', async function () {
+ // Emit events
+ await expect(this.mock.connect(this.newDefaultAdmin).acceptDefaultAdminTransfer())
+ .to.emit(this.mock, 'RoleRevoked')
+ .withArgs(DEFAULT_ADMIN_ROLE, this.defaultAdmin, this.newDefaultAdmin)
+ .to.emit(this.mock, 'RoleGranted')
+ .withArgs(DEFAULT_ADMIN_ROLE, this.newDefaultAdmin, this.newDefaultAdmin);
+
+ // Storage changes
+ expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin)).to.be.false;
+ expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, this.newDefaultAdmin)).to.be.true;
+ expect(await this.mock.owner()).to.equal(this.newDefaultAdmin);
+
+ // Resets pending default admin and schedule
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(0);
+ });
+ });
+
+ describe('schedule not passed', function () {
+ for (const [fromSchedule, tag] of [
+ [-1n, 'less'],
+ [0n, 'equal'],
+ ]) {
+ it(`should revert if block.timestamp is ${tag} to schedule`, async function () {
+ await time.increaseTo.timestamp(this.acceptSchedule + fromSchedule, false);
+ await expect(this.mock.connect(this.newDefaultAdmin).acceptDefaultAdminTransfer())
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlEnforcedDefaultAdminDelay')
+ .withArgs(this.acceptSchedule);
+ });
+ }
+ });
+ });
+
+ describe('cancels a default admin transfer', function () {
+ it('reverts if called by non default admin accounts', async function () {
+ await expect(this.mock.connect(this.other).cancelDefaultAdminTransfer())
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, DEFAULT_ADMIN_ROLE);
+ });
+
+ describe('when there is a pending default admin transfer', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(this.newDefaultAdmin);
+ this.acceptSchedule = (await time.clock.timestamp()) + this.delay;
+ });
+
+ for (const [fromSchedule, tag] of [
+ [-1n, 'before'],
+ [0n, 'exactly when'],
+ [1n, 'after'],
+ ]) {
+ it(`resets pending default admin and schedule ${tag} transfer schedule passes`, async function () {
+ // Advance until passed delay
+ await time.increaseTo.timestamp(this.acceptSchedule + fromSchedule, false);
+
+ await expect(this.mock.connect(this.defaultAdmin).cancelDefaultAdminTransfer()).to.emit(
+ this.mock,
+ 'DefaultAdminTransferCanceled',
+ );
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(0);
+ });
+ }
+
+ it('should revert if the previous default admin tries to accept', async function () {
+ await this.mock.connect(this.defaultAdmin).cancelDefaultAdminTransfer();
+
+ // Advance until passed delay
+ await time.increaseTo.timestamp(this.acceptSchedule + 1n, false);
+
+ // Previous pending default admin should not be able to accept after cancellation.
+ await expect(this.mock.connect(this.newDefaultAdmin).acceptDefaultAdminTransfer())
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlInvalidDefaultAdmin')
+ .withArgs(this.newDefaultAdmin);
+ });
+ });
+
+ describe('when there is no pending default admin transfer', function () {
+ it('should succeed without changes', async function () {
+ await expect(this.mock.connect(this.defaultAdmin).cancelDefaultAdminTransfer()).to.not.emit(
+ this.mock,
+ 'DefaultAdminTransferCanceled',
+ );
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(0);
+ });
+ });
+ });
+
+ describe('renounces admin', function () {
+ beforeEach(async function () {
+ await this.mock.connect(this.defaultAdmin).beginDefaultAdminTransfer(ethers.ZeroAddress);
+ this.expectedSchedule = (await time.clock.timestamp()) + this.delay;
+ });
+
+ it('reverts if caller is not default admin', async function () {
+ await time.increaseBy.timestamp(this.delay + 1n, false);
+ await expect(
+ this.mock.connect(this.defaultAdmin).renounceRole(DEFAULT_ADMIN_ROLE, this.other),
+ ).to.be.revertedWithCustomError(this.mock, 'AccessControlBadConfirmation');
+ });
+
+ it("renouncing the admin role when not an admin doesn't affect the schedule", async function () {
+ await time.increaseBy.timestamp(this.delay + 1n, false);
+ await this.mock.connect(this.other).renounceRole(DEFAULT_ADMIN_ROLE, this.other);
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(this.expectedSchedule);
+ });
+
+ it('keeps defaultAdmin consistent with hasRole if another non-defaultAdmin user renounces the DEFAULT_ADMIN_ROLE', async function () {
+ await time.increaseBy.timestamp(this.delay + 1n, false);
+
+ // This passes because it's a noop
+ await this.mock.connect(this.other).renounceRole(DEFAULT_ADMIN_ROLE, this.other);
+
+ expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin)).to.be.true;
+ expect(await this.mock.defaultAdmin()).to.equal(this.defaultAdmin);
+ });
+
+ it('renounces role', async function () {
+ await time.increaseBy.timestamp(this.delay + 1n, false);
+ await expect(this.mock.connect(this.defaultAdmin).renounceRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin))
+ .to.emit(this.mock, 'RoleRevoked')
+ .withArgs(DEFAULT_ADMIN_ROLE, this.defaultAdmin, this.defaultAdmin);
+
+ expect(await this.mock.hasRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin)).to.be.false;
+ expect(await this.mock.defaultAdmin()).to.equal(ethers.ZeroAddress);
+ expect(await this.mock.owner()).to.equal(ethers.ZeroAddress);
+
+ const { newAdmin, schedule } = await this.mock.pendingDefaultAdmin();
+ expect(newAdmin).to.equal(ethers.ZeroAddress);
+ expect(schedule).to.equal(0);
+ });
+
+ it('allows to recover access using the internal _grantRole', async function () {
+ await time.increaseBy.timestamp(this.delay + 1n, false);
+ await this.mock.connect(this.defaultAdmin).renounceRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin);
+
+ await expect(this.mock.connect(this.defaultAdmin).$_grantRole(DEFAULT_ADMIN_ROLE, this.other))
+ .to.emit(this.mock, 'RoleGranted')
+ .withArgs(DEFAULT_ADMIN_ROLE, this.other, this.defaultAdmin);
+ });
+
+ describe('schedule not passed', function () {
+ for (const [fromSchedule, tag] of [
+ [-1n, 'less'],
+ [0n, 'equal'],
+ ]) {
+ it(`reverts if block.timestamp is ${tag} to schedule`, async function () {
+ await time.increaseBy.timestamp(this.delay + fromSchedule, false);
+ await expect(this.mock.connect(this.defaultAdmin).renounceRole(DEFAULT_ADMIN_ROLE, this.defaultAdmin))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlEnforcedDefaultAdminDelay')
+ .withArgs(this.expectedSchedule);
+ });
+ }
+ });
+ });
+
+ describe('changes delay', function () {
+ it('reverts if called by non default admin accounts', async function () {
+ await expect(this.mock.connect(this.other).changeDefaultAdminDelay(time.duration.hours(4)))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, DEFAULT_ADMIN_ROLE);
+ });
+
+ for (const [delayDifference, delayChangeType] of [
+ [time.duration.hours(-1), 'decreased'],
+ [time.duration.hours(1), 'increased'],
+ [time.duration.days(5), 'increased to more than 5 days'],
+ ]) {
+ describe(`when the delay is ${delayChangeType}`, function () {
+ beforeEach(function () {
+ this.newDefaultAdminDelay = this.delay + delayDifference;
+ });
+
+ it('begins the delay change to the new delay', async function () {
+ // Calculate expected values
+ const capWait = await this.mock.defaultAdminDelayIncreaseWait();
+ const minWait = capWait < this.newDefaultAdminDelay ? capWait : this.newDefaultAdminDelay;
+ const changeDelay =
+ this.newDefaultAdminDelay <= this.delay ? this.delay - this.newDefaultAdminDelay : minWait;
+ const nextBlockTimestamp = (await time.clock.timestamp()) + 1n;
+ const effectSchedule = nextBlockTimestamp + changeDelay;
+
+ await time.increaseTo.timestamp(nextBlockTimestamp, false);
+
+ // Begins the change
+ await expect(this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(this.newDefaultAdminDelay))
+ .to.emit(this.mock, 'DefaultAdminDelayChangeScheduled')
+ .withArgs(this.newDefaultAdminDelay, effectSchedule);
+
+ // Assert
+ const { newDelay, schedule } = await this.mock.pendingDefaultAdminDelay();
+ expect(newDelay).to.equal(this.newDefaultAdminDelay);
+ expect(schedule).to.equal(effectSchedule);
+ });
+
+ describe('scheduling again', function () {
+ beforeEach('schedule once', async function () {
+ await this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(this.newDefaultAdminDelay);
+ });
+
+ for (const [fromSchedule, tag] of [
+ [-1n, 'before'],
+ [0n, 'exactly when'],
+ [1n, 'after'],
+ ]) {
+ const passed = fromSchedule > 0;
+
+ it(`succeeds ${tag} the delay schedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdminDelay();
+ const nextBlockTimestamp = firstSchedule + fromSchedule;
+ await time.increaseTo.timestamp(nextBlockTimestamp, false);
+
+ // Calculate expected values
+ const anotherNewDefaultAdminDelay = this.newDefaultAdminDelay + time.duration.hours(2);
+ const capWait = await this.mock.defaultAdminDelayIncreaseWait();
+ const minWait = capWait < anotherNewDefaultAdminDelay ? capWait : anotherNewDefaultAdminDelay;
+ const effectSchedule = nextBlockTimestamp + minWait;
+
+ // Default admin changes its mind and begins another delay change
+ await expect(this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(anotherNewDefaultAdminDelay))
+ .to.emit(this.mock, 'DefaultAdminDelayChangeScheduled')
+ .withArgs(anotherNewDefaultAdminDelay, effectSchedule);
+
+ // Assert
+ const { newDelay, schedule } = await this.mock.pendingDefaultAdminDelay();
+ expect(newDelay).to.equal(anotherNewDefaultAdminDelay);
+ expect(schedule).to.equal(effectSchedule);
+ });
+
+ const emit = passed ? 'not emit' : 'emit';
+ it(`should ${emit} a cancellation event ${tag} the delay schedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdminDelay();
+ await time.increaseTo.timestamp(firstSchedule + fromSchedule, false);
+
+ // Default admin changes its mind and begins another delay change
+ const anotherNewDefaultAdminDelay = this.newDefaultAdminDelay + time.duration.hours(2);
+
+ const expected = expect(
+ this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(anotherNewDefaultAdminDelay),
+ );
+ if (passed) {
+ await expected.to.not.emit(this.mock, 'DefaultAdminDelayChangeCanceled');
+ } else {
+ await expected.to.emit(this.mock, 'DefaultAdminDelayChangeCanceled');
+ }
+ });
+ }
+ });
+ });
+ }
+ });
+
+ describe('rollbacks a delay change', function () {
+ it('reverts if called by non default admin accounts', async function () {
+ await expect(this.mock.connect(this.other).rollbackDefaultAdminDelay())
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, DEFAULT_ADMIN_ROLE);
+ });
+
+ describe('when there is a pending delay', function () {
+ beforeEach('set pending delay', async function () {
+ await this.mock.connect(this.defaultAdmin).changeDefaultAdminDelay(time.duration.hours(12));
+ });
+
+ for (const [fromSchedule, tag] of [
+ [-1n, 'before'],
+ [0n, 'exactly when'],
+ [1n, 'after'],
+ ]) {
+ const passed = fromSchedule > 0;
+
+ it(`resets pending delay and schedule ${tag} delay change schedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdminDelay();
+ await time.increaseTo.timestamp(firstSchedule + fromSchedule, false);
+
+ await this.mock.connect(this.defaultAdmin).rollbackDefaultAdminDelay();
+
+ const { newDelay, schedule } = await this.mock.pendingDefaultAdminDelay();
+ expect(newDelay).to.equal(0);
+ expect(schedule).to.equal(0);
+ });
+
+ const emit = passed ? 'not emit' : 'emit';
+ it(`should ${emit} a cancellation event ${tag} the delay schedule passes`, async function () {
+ // Wait until schedule + fromSchedule
+ const { schedule: firstSchedule } = await this.mock.pendingDefaultAdminDelay();
+ await time.increaseTo.timestamp(firstSchedule + fromSchedule, false);
+
+ const expected = expect(this.mock.connect(this.defaultAdmin).rollbackDefaultAdminDelay());
+ if (passed) {
+ await expected.to.not.emit(this.mock, 'DefaultAdminDelayChangeCanceled');
+ } else {
+ await expected.to.emit(this.mock, 'DefaultAdminDelayChangeCanceled');
+ }
+ });
+ }
+ });
+
+ describe('when there is no pending delay', function () {
+ it('succeeds without changes', async function () {
+ await this.mock.connect(this.defaultAdmin).rollbackDefaultAdminDelay();
+
+ const { newDelay, schedule } = await this.mock.pendingDefaultAdminDelay();
+ expect(newDelay).to.equal(0);
+ expect(schedule).to.equal(0);
+ });
+ });
+ });
+}
+
+module.exports = {
+ DEFAULT_ADMIN_ROLE,
+ shouldBehaveLikeAccessControl,
+ shouldBehaveLikeAccessControlEnumerable,
+ shouldBehaveLikeAccessControlDefaultAdminRules,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/AccessControl.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/AccessControl.test.js
new file mode 100644
index 000000000..5c70cdc6d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/AccessControl.test.js
@@ -0,0 +1,19 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { DEFAULT_ADMIN_ROLE, shouldBehaveLikeAccessControl } = require('./AccessControl.behavior');
+
+async function fixture() {
+ const [defaultAdmin, ...accounts] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$AccessControl');
+ await mock.$_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
+ return { mock, defaultAdmin, accounts };
+}
+
+describe('AccessControl', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeAccessControl();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/Ownable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/Ownable.test.js
new file mode 100644
index 000000000..2d9b561a1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/Ownable.test.js
@@ -0,0 +1,79 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [owner, other] = await ethers.getSigners();
+ const ownable = await ethers.deployContract('$Ownable', [owner]);
+ return { owner, other, ownable };
+}
+
+describe('Ownable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('emits ownership transfer events during construction', async function () {
+ await expect(this.ownable.deploymentTransaction())
+ .to.emit(this.ownable, 'OwnershipTransferred')
+ .withArgs(ethers.ZeroAddress, this.owner);
+ });
+
+ it('rejects zero address for initialOwner', async function () {
+ await expect(ethers.deployContract('$Ownable', [ethers.ZeroAddress]))
+ .to.be.revertedWithCustomError({ interface: this.ownable.interface }, 'OwnableInvalidOwner')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('has an owner', async function () {
+ expect(await this.ownable.owner()).to.equal(this.owner);
+ });
+
+ describe('transfer ownership', function () {
+ it('changes owner after transfer', async function () {
+ await expect(this.ownable.connect(this.owner).transferOwnership(this.other))
+ .to.emit(this.ownable, 'OwnershipTransferred')
+ .withArgs(this.owner, this.other);
+
+ expect(await this.ownable.owner()).to.equal(this.other);
+ });
+
+ it('prevents non-owners from transferring', async function () {
+ await expect(this.ownable.connect(this.other).transferOwnership(this.other))
+ .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
+ .withArgs(this.other);
+ });
+
+ it('guards ownership against stuck state', async function () {
+ await expect(this.ownable.connect(this.owner).transferOwnership(ethers.ZeroAddress))
+ .to.be.revertedWithCustomError(this.ownable, 'OwnableInvalidOwner')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('renounce ownership', function () {
+ it('loses ownership after renouncement', async function () {
+ await expect(this.ownable.connect(this.owner).renounceOwnership())
+ .to.emit(this.ownable, 'OwnershipTransferred')
+ .withArgs(this.owner, ethers.ZeroAddress);
+
+ expect(await this.ownable.owner()).to.equal(ethers.ZeroAddress);
+ });
+
+ it('prevents non-owners from renouncement', async function () {
+ await expect(this.ownable.connect(this.other).renounceOwnership())
+ .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
+ .withArgs(this.other);
+ });
+
+ it('allows to recover access using the internal _transferOwnership', async function () {
+ await this.ownable.connect(this.owner).renounceOwnership();
+
+ await expect(this.ownable.$_transferOwnership(this.other))
+ .to.emit(this.ownable, 'OwnershipTransferred')
+ .withArgs(ethers.ZeroAddress, this.other);
+
+ expect(await this.ownable.owner()).to.equal(this.other);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/Ownable2Step.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/Ownable2Step.test.js
new file mode 100644
index 000000000..5620a2491
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/Ownable2Step.test.js
@@ -0,0 +1,102 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [owner, accountA, accountB] = await ethers.getSigners();
+ const ownable2Step = await ethers.deployContract('$Ownable2Step', [owner]);
+ return {
+ ownable2Step,
+ owner,
+ accountA,
+ accountB,
+ };
+}
+
+describe('Ownable2Step', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('transfer ownership', function () {
+ it('starting a transfer does not change owner', async function () {
+ await expect(this.ownable2Step.connect(this.owner).transferOwnership(this.accountA))
+ .to.emit(this.ownable2Step, 'OwnershipTransferStarted')
+ .withArgs(this.owner, this.accountA);
+
+ expect(await this.ownable2Step.owner()).to.equal(this.owner);
+ expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA);
+ });
+
+ it('changes owner after transfer', async function () {
+ await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
+
+ await expect(this.ownable2Step.connect(this.accountA).acceptOwnership())
+ .to.emit(this.ownable2Step, 'OwnershipTransferred')
+ .withArgs(this.owner, this.accountA);
+
+ expect(await this.ownable2Step.owner()).to.equal(this.accountA);
+ expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress);
+ });
+
+ it('guards transfer against invalid user', async function () {
+ await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
+
+ await expect(this.ownable2Step.connect(this.accountB).acceptOwnership())
+ .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount')
+ .withArgs(this.accountB);
+ });
+ });
+
+ describe('renouncing ownership', function () {
+ it('changes owner after renouncing ownership', async function () {
+ await expect(this.ownable2Step.connect(this.owner).renounceOwnership())
+ .to.emit(this.ownable2Step, 'OwnershipTransferred')
+ .withArgs(this.owner, ethers.ZeroAddress);
+
+ // If renounceOwnership is removed from parent an alternative is needed ...
+ // without it is difficult to cleanly renounce with the two step process
+ // see: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3620#discussion_r957930388
+ expect(await this.ownable2Step.owner()).to.equal(ethers.ZeroAddress);
+ });
+
+ it('pending owner resets after renouncing ownership', async function () {
+ await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
+ expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA);
+
+ await this.ownable2Step.connect(this.owner).renounceOwnership();
+ expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress);
+
+ await expect(this.ownable2Step.connect(this.accountA).acceptOwnership())
+ .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount')
+ .withArgs(this.accountA);
+ });
+
+ it('allows to recover access using the internal _transferOwnership', async function () {
+ await this.ownable2Step.connect(this.owner).renounceOwnership();
+
+ await expect(this.ownable2Step.$_transferOwnership(this.accountA))
+ .to.emit(this.ownable2Step, 'OwnershipTransferred')
+ .withArgs(ethers.ZeroAddress, this.accountA);
+
+ expect(await this.ownable2Step.owner()).to.equal(this.accountA);
+ });
+
+ it('allows the owner to cancel an initiated ownership transfer by setting newOwner to zero address', async function () {
+ // initiate ownership transfer to accountA
+ await this.ownable2Step.connect(this.owner).transferOwnership(this.accountA);
+ expect(await this.ownable2Step.pendingOwner()).to.equal(this.accountA);
+
+ // cancel the ownership transfer by setting newOwner to zero address
+ await expect(this.ownable2Step.connect(this.owner).transferOwnership(ethers.ZeroAddress))
+ .to.emit(this.ownable2Step, 'OwnershipTransferStarted')
+ .withArgs(this.owner, ethers.ZeroAddress);
+ expect(await this.ownable2Step.pendingOwner()).to.equal(ethers.ZeroAddress);
+
+ // verify that accountA cannot accept ownership anymore
+ await expect(this.ownable2Step.connect(this.accountA).acceptOwnership())
+ .to.be.revertedWithCustomError(this.ownable2Step, 'OwnableUnauthorizedAccount')
+ .withArgs(this.accountA);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/extensions/AccessControlDefaultAdminRules.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/extensions/AccessControlDefaultAdminRules.test.js
new file mode 100644
index 000000000..48036fd9b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/extensions/AccessControlDefaultAdminRules.test.js
@@ -0,0 +1,32 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const time = require('../../helpers/time');
+
+const {
+ shouldBehaveLikeAccessControl,
+ shouldBehaveLikeAccessControlDefaultAdminRules,
+} = require('../AccessControl.behavior');
+
+async function fixture() {
+ const delay = time.duration.hours(10);
+ const [defaultAdmin, ...accounts] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$AccessControlDefaultAdminRules', [delay, defaultAdmin]);
+ return { mock, defaultAdmin, delay, accounts };
+}
+
+describe('AccessControlDefaultAdminRules', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('initial admin not zero', async function () {
+ await expect(ethers.deployContract('$AccessControlDefaultAdminRules', [this.delay, ethers.ZeroAddress]))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlInvalidDefaultAdmin')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ shouldBehaveLikeAccessControl();
+ shouldBehaveLikeAccessControlDefaultAdminRules();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/extensions/AccessControlEnumerable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/extensions/AccessControlEnumerable.test.js
new file mode 100644
index 000000000..ea1a8c46f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/extensions/AccessControlEnumerable.test.js
@@ -0,0 +1,24 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const {
+ DEFAULT_ADMIN_ROLE,
+ shouldBehaveLikeAccessControl,
+ shouldBehaveLikeAccessControlEnumerable,
+} = require('../AccessControl.behavior');
+
+async function fixture() {
+ const [defaultAdmin, ...accounts] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$AccessControlEnumerable');
+ await mock.$_grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin);
+ return { mock, defaultAdmin, accounts };
+}
+
+describe('AccessControlEnumerable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeAccessControl();
+ shouldBehaveLikeAccessControlEnumerable();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManaged.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManaged.test.js
new file mode 100644
index 000000000..d666b5e6d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManaged.test.js
@@ -0,0 +1,146 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { impersonate } = require('../../helpers/account');
+const time = require('../../helpers/time');
+
+async function fixture() {
+ const [admin, roleMember, other] = await ethers.getSigners();
+
+ const authority = await ethers.deployContract('$AccessManager', [admin]);
+ const managed = await ethers.deployContract('$AccessManagedTarget', [authority]);
+
+ const anotherAuthority = await ethers.deployContract('$AccessManager', [admin]);
+ const authorityObserveIsConsuming = await ethers.deployContract('$AuthorityObserveIsConsuming');
+
+ await impersonate(authority.target);
+ const authorityAsSigner = await ethers.getSigner(authority.target);
+
+ return {
+ roleMember,
+ other,
+ authorityAsSigner,
+ authority,
+ managed,
+ authorityObserveIsConsuming,
+ anotherAuthority,
+ };
+}
+
+describe('AccessManaged', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('sets authority and emits AuthorityUpdated event during construction', async function () {
+ await expect(this.managed.deploymentTransaction())
+ .to.emit(this.managed, 'AuthorityUpdated')
+ .withArgs(this.authority);
+ });
+
+ describe('restricted modifier', function () {
+ beforeEach(async function () {
+ this.selector = this.managed.fnRestricted.getFragment().selector;
+ this.role = 42n;
+ await this.authority.$_setTargetFunctionRole(this.managed, this.selector, this.role);
+ await this.authority.$_grantRole(this.role, this.roleMember, 0, 0);
+ });
+
+ it('succeeds when role is granted without execution delay', async function () {
+ await this.managed.connect(this.roleMember)[this.selector]();
+ });
+
+ it('reverts when role is not granted', async function () {
+ await expect(this.managed.connect(this.other)[this.selector]())
+ .to.be.revertedWithCustomError(this.managed, 'AccessManagedUnauthorized')
+ .withArgs(this.other);
+ });
+
+ it('panics in short calldata', async function () {
+ // We avoid adding the `restricted` modifier to the fallback function because other tests may depend on it
+ // being accessible without restrictions. We check for the internal `_checkCanCall` instead.
+ await expect(this.managed.$_checkCanCall(this.roleMember, '0x1234')).to.be.reverted;
+ });
+
+ describe('when role is granted with execution delay', function () {
+ beforeEach(async function () {
+ const executionDelay = 911n;
+ await this.authority.$_grantRole(this.role, this.roleMember, 0, executionDelay);
+ });
+
+ it('reverts if the operation is not scheduled', async function () {
+ const fn = this.managed.interface.getFunction(this.selector);
+ const calldata = this.managed.interface.encodeFunctionData(fn, []);
+ const opId = await this.authority.hashOperation(this.roleMember, this.managed, calldata);
+
+ await expect(this.managed.connect(this.roleMember)[this.selector]())
+ .to.be.revertedWithCustomError(this.authority, 'AccessManagerNotScheduled')
+ .withArgs(opId);
+ });
+
+ it('succeeds if the operation is scheduled', async function () {
+ // Arguments
+ const delay = time.duration.hours(12);
+ const fn = this.managed.interface.getFunction(this.selector);
+ const calldata = this.managed.interface.encodeFunctionData(fn, []);
+
+ // Schedule
+ const scheduledAt = (await time.clock.timestamp()) + 1n;
+ const when = scheduledAt + delay;
+ await time.increaseTo.timestamp(scheduledAt, false);
+ await this.authority.connect(this.roleMember).schedule(this.managed, calldata, when);
+
+ // Set execution date
+ await time.increaseTo.timestamp(when, false);
+
+ // Shouldn't revert
+ await this.managed.connect(this.roleMember)[this.selector]();
+ });
+ });
+ });
+
+ describe('setAuthority', function () {
+ it('reverts if the caller is not the authority', async function () {
+ await expect(this.managed.connect(this.other).setAuthority(this.other))
+ .to.be.revertedWithCustomError(this.managed, 'AccessManagedUnauthorized')
+ .withArgs(this.other);
+ });
+
+ it('reverts if the new authority is not a valid authority', async function () {
+ await expect(this.managed.connect(this.authorityAsSigner).setAuthority(this.other))
+ .to.be.revertedWithCustomError(this.managed, 'AccessManagedInvalidAuthority')
+ .withArgs(this.other);
+ });
+
+ it('sets authority and emits AuthorityUpdated event', async function () {
+ await expect(this.managed.connect(this.authorityAsSigner).setAuthority(this.anotherAuthority))
+ .to.emit(this.managed, 'AuthorityUpdated')
+ .withArgs(this.anotherAuthority);
+
+ expect(await this.managed.authority()).to.equal(this.anotherAuthority);
+ });
+ });
+
+ describe('isConsumingScheduledOp', function () {
+ beforeEach(async function () {
+ await this.managed.connect(this.authorityAsSigner).setAuthority(this.authorityObserveIsConsuming);
+ });
+
+ it('returns bytes4(0) when not consuming operation', async function () {
+ expect(await this.managed.isConsumingScheduledOp()).to.equal('0x00000000');
+ });
+
+ it('returns isConsumingScheduledOp selector when consuming operation', async function () {
+ const isConsumingScheduledOp = this.managed.interface.getFunction('isConsumingScheduledOp()');
+ const fnRestricted = this.managed.fnRestricted.getFragment();
+ await expect(this.managed.connect(this.other).fnRestricted())
+ .to.emit(this.authorityObserveIsConsuming, 'ConsumeScheduledOpCalled')
+ .withArgs(
+ this.other,
+ this.managed.interface.encodeFunctionData(fnRestricted, []),
+ isConsumingScheduledOp.selector,
+ );
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.behavior.js
new file mode 100644
index 000000000..385da578c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.behavior.js
@@ -0,0 +1,257 @@
+const { expect } = require('chai');
+
+const {
+ LIKE_COMMON_IS_EXECUTING,
+ LIKE_COMMON_GET_ACCESS,
+ LIKE_COMMON_SCHEDULABLE,
+ testAsSchedulableOperation,
+ testAsRestrictedOperation,
+ testAsDelayedOperation,
+ testAsCanCall,
+ testAsHasRole,
+} = require('./AccessManager.predicate');
+
+// ============ ADMIN OPERATION ============
+
+/**
+ * @requires this.{manager,roles,calldata,role}
+ */
+function shouldBehaveLikeDelayedAdminOperation() {
+ const getAccessPath = LIKE_COMMON_GET_ACCESS;
+ testAsDelayedOperation.mineDelay = true;
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay =
+ testAsDelayedOperation;
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = function () {
+ beforeEach('set execution delay', async function () {
+ this.scheduleIn = this.executionDelay; // For testAsDelayedOperation
+ });
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ };
+
+ beforeEach('set target as manager', function () {
+ this.target = this.manager;
+ });
+
+ testAsRestrictedOperation({
+ callerIsTheManager: LIKE_COMMON_IS_EXECUTING,
+ callerIsNotTheManager() {
+ testAsHasRole({
+ publicRoleIsRequired() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.target, 'AccessManagerUnauthorizedAccount')
+ .withArgs(
+ this.caller,
+ this.roles.ADMIN.id, // Although PUBLIC is required, target function role doesn't apply to admin ops
+ );
+ });
+ },
+ specificRoleIsRequired: getAccessPath,
+ });
+ },
+ });
+}
+
+/**
+ * @requires this.{manager,roles,calldata,role}
+ */
+function shouldBehaveLikeNotDelayedAdminOperation() {
+ const getAccessPath = LIKE_COMMON_GET_ACCESS;
+
+ function testScheduleOperation(mineDelay) {
+ return function self() {
+ self.mineDelay = mineDelay;
+ beforeEach('set execution delay', async function () {
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ };
+ }
+
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay =
+ testScheduleOperation(true);
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = testScheduleOperation(false);
+
+ beforeEach('set target as manager', function () {
+ this.target = this.manager;
+ });
+
+ testAsRestrictedOperation({
+ callerIsTheManager: LIKE_COMMON_IS_EXECUTING,
+ callerIsNotTheManager() {
+ testAsHasRole({
+ publicRoleIsRequired() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.target, 'AccessManagerUnauthorizedAccount')
+ .withArgs(
+ this.caller,
+ this.roles.ADMIN.id, // Although PUBLIC_ROLE is required, admin ops are not subject to target function roles
+ );
+ });
+ },
+ specificRoleIsRequired: getAccessPath,
+ });
+ },
+ });
+}
+
+/**
+ * @requires this.{manager,roles,calldata,role}
+ */
+function shouldBehaveLikeRoleAdminOperation(roleAdmin) {
+ const getAccessPath = LIKE_COMMON_GET_ACCESS;
+
+ function afterGrantDelay() {
+ afterGrantDelay.mineDelay = true;
+ beforeEach('set execution delay', async function () {
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ }
+
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay = afterGrantDelay;
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = afterGrantDelay;
+
+ beforeEach('set target as manager', function () {
+ this.target = this.manager;
+ });
+
+ testAsRestrictedOperation({
+ callerIsTheManager: LIKE_COMMON_IS_EXECUTING,
+ callerIsNotTheManager() {
+ testAsHasRole({
+ publicRoleIsRequired() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.target, 'AccessManagerUnauthorizedAccount')
+ .withArgs(this.caller, roleAdmin);
+ });
+ },
+ specificRoleIsRequired: getAccessPath,
+ });
+ },
+ });
+}
+
+// ============ RESTRICTED OPERATION ============
+
+/**
+ * @requires this.{manager,roles,calldata,role}
+ */
+function shouldBehaveLikeAManagedRestrictedOperation() {
+ function revertUnauthorized() {
+ it('reverts as AccessManagedUnauthorized', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.target, 'AccessManagedUnauthorized')
+ .withArgs(this.caller);
+ });
+ }
+
+ const getAccessPath = LIKE_COMMON_GET_ACCESS;
+
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.beforeGrantDelay =
+ revertUnauthorized;
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasNoExecutionDelay.beforeGrantDelay =
+ revertUnauthorized;
+ getAccessPath.requiredRoleIsNotGranted = revertUnauthorized;
+
+ function testScheduleOperation(mineDelay) {
+ return function self() {
+ self.mineDelay = mineDelay;
+ beforeEach('sets execution delay', async function () {
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ };
+ }
+
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay =
+ testScheduleOperation(true);
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = testScheduleOperation(false);
+
+ const isExecutingPath = LIKE_COMMON_IS_EXECUTING;
+ isExecutingPath.notExecuting = revertUnauthorized;
+
+ testAsCanCall({
+ closed: revertUnauthorized,
+ open: {
+ callerIsTheManager: isExecutingPath,
+ callerIsNotTheManager: {
+ publicRoleIsRequired() {
+ it('succeeds called directly', async function () {
+ await this.caller.sendTransaction({ to: this.target, data: this.calldata });
+ });
+
+ it('succeeds via execute', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ specificRoleIsRequired: getAccessPath,
+ },
+ },
+ });
+}
+
+/**
+ * @requires this.{target,manager,roles,calldata,role}
+ */
+function shouldBehaveLikeASelfRestrictedOperation() {
+ function revertUnauthorized() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedAccount')
+ .withArgs(this.caller, this.role?.id ?? 0n);
+ });
+ }
+
+ const getAccessPath = LIKE_COMMON_GET_ACCESS;
+
+ function testScheduleOperation(mineDelay) {
+ return function self() {
+ self.mineDelay = mineDelay;
+ beforeEach('sets execution delay', async function () {
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ };
+ }
+
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsDelayed.callerHasAnExecutionDelay.afterGrantDelay =
+ testScheduleOperation(true);
+ getAccessPath.requiredRoleIsGranted.roleGrantingIsNotDelayed.callerHasAnExecutionDelay = testScheduleOperation(false);
+
+ beforeEach('set target as manager', function () {
+ this.target = this.manager;
+ });
+
+ const isExecutingPath = LIKE_COMMON_IS_EXECUTING;
+ isExecutingPath.notExecuting = revertUnauthorized;
+
+ testAsCanCall({
+ closed: revertUnauthorized,
+ open: {
+ callerIsTheManager: isExecutingPath,
+ callerIsNotTheManager: {
+ publicRoleIsRequired() {
+ it('succeeds called directly', async function () {
+ await this.caller.sendTransaction({ to: this.target, data: this.calldata });
+ });
+
+ it('succeeds via execute', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ specificRoleIsRequired: getAccessPath,
+ },
+ },
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeDelayedAdminOperation,
+ shouldBehaveLikeNotDelayedAdminOperation,
+ shouldBehaveLikeRoleAdminOperation,
+ shouldBehaveLikeAManagedRestrictedOperation,
+ shouldBehaveLikeASelfRestrictedOperation,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.predicate.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.predicate.js
new file mode 100644
index 000000000..8b4c5f4b6
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.predicate.js
@@ -0,0 +1,456 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { setStorageAt } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { EXECUTION_ID_STORAGE_SLOT, EXPIRATION, prepareOperation } = require('../../helpers/access-manager');
+const { impersonate } = require('../../helpers/account');
+const time = require('../../helpers/time');
+
+// ============ COMMON PREDICATES ============
+
+const LIKE_COMMON_IS_EXECUTING = {
+ executing() {
+ it('succeeds', async function () {
+ await this.caller.sendTransaction({ to: this.target, data: this.calldata });
+ });
+ },
+ notExecuting() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedAccount')
+ .withArgs(this.caller, this.role.id);
+ });
+ },
+};
+
+const LIKE_COMMON_GET_ACCESS = {
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ callerHasAnExecutionDelay: {
+ beforeGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedAccount')
+ .withArgs(this.caller, this.role.id);
+ });
+ },
+ afterGrantDelay: undefined, // Diverges if there's an operation delay or not
+ },
+ callerHasNoExecutionDelay: {
+ beforeGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedAccount')
+ .withArgs(this.caller, this.role.id);
+ });
+ },
+ afterGrantDelay() {
+ it('succeeds called directly', async function () {
+ await this.caller.sendTransaction({ to: this.target, data: this.calldata });
+ });
+
+ it('succeeds via execute', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ },
+ },
+ roleGrantingIsNotDelayed: {
+ callerHasAnExecutionDelay: undefined, // Diverges if there's an operation to schedule or not
+ callerHasNoExecutionDelay() {
+ it('succeeds called directly', async function () {
+ await this.caller.sendTransaction({ to: this.target, data: this.calldata });
+ });
+
+ it('succeeds via execute', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ },
+ },
+ requiredRoleIsNotGranted() {
+ it('reverts as AccessManagerUnauthorizedAccount', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedAccount')
+ .withArgs(this.caller, this.role.id);
+ });
+ },
+};
+
+const LIKE_COMMON_SCHEDULABLE = {
+ scheduled: {
+ before() {
+ it('reverts as AccessManagerNotReady', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotReady')
+ .withArgs(this.operationId);
+ });
+ },
+ after() {
+ it('succeeds called directly', async function () {
+ await this.caller.sendTransaction({ to: this.target, data: this.calldata });
+ });
+
+ it('succeeds via execute', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ expired() {
+ it('reverts as AccessManagerExpired', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerExpired')
+ .withArgs(this.operationId);
+ });
+ },
+ },
+ notScheduled() {
+ it('reverts as AccessManagerNotScheduled', async function () {
+ await expect(this.caller.sendTransaction({ to: this.target, data: this.calldata }))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
+ .withArgs(this.operationId);
+ });
+ },
+};
+
+// ============ MODE ============
+
+/**
+ * @requires this.{manager,target}
+ */
+function testAsClosable({ closed, open }) {
+ describe('when the manager is closed', function () {
+ beforeEach('close', async function () {
+ await this.manager.$_setTargetClosed(this.target, true);
+ });
+
+ closed();
+ });
+
+ describe('when the manager is open', function () {
+ beforeEach('open', async function () {
+ await this.manager.$_setTargetClosed(this.target, false);
+ });
+
+ open();
+ });
+}
+
+// ============ DELAY ============
+
+/**
+ * @requires this.{delay}
+ */
+function testAsDelay(type, { before, after }) {
+ beforeEach('define timestamp when delay takes effect', async function () {
+ const timestamp = await time.clock.timestamp();
+ this.delayEffect = timestamp + this.delay;
+ });
+
+ describe(`when ${type} delay has not taken effect yet`, function () {
+ beforeEach(`set next block timestamp before ${type} takes effect`, async function () {
+ await time.increaseTo.timestamp(this.delayEffect - 1n, !!before.mineDelay);
+ });
+
+ before();
+ });
+
+ describe(`when ${type} delay has taken effect`, function () {
+ beforeEach(`set next block timestamp when ${type} takes effect`, async function () {
+ await time.increaseTo.timestamp(this.delayEffect, !!after.mineDelay);
+ });
+
+ after();
+ });
+}
+
+// ============ OPERATION ============
+
+/**
+ * @requires this.{manager,scheduleIn,caller,target,calldata}
+ */
+function testAsSchedulableOperation({ scheduled: { before, after, expired }, notScheduled }) {
+ describe('when operation is scheduled', function () {
+ beforeEach('schedule operation', async function () {
+ if (this.caller.target) {
+ await impersonate(this.caller.target);
+ this.caller = await ethers.getSigner(this.caller.target);
+ }
+ const { operationId, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.scheduleIn,
+ });
+ await schedule();
+ this.operationId = operationId;
+ });
+
+ describe('when operation is not ready for execution', function () {
+ beforeEach('set next block time before operation is ready', async function () {
+ this.scheduledAt = await time.clock.timestamp();
+ const schedule = await this.manager.getSchedule(this.operationId);
+ await time.increaseTo.timestamp(schedule - 1n, !!before.mineDelay);
+ });
+
+ before();
+ });
+
+ describe('when operation is ready for execution', function () {
+ beforeEach('set next block time when operation is ready for execution', async function () {
+ this.scheduledAt = await time.clock.timestamp();
+ const schedule = await this.manager.getSchedule(this.operationId);
+ await time.increaseTo.timestamp(schedule, !!after.mineDelay);
+ });
+
+ after();
+ });
+
+ describe('when operation has expired', function () {
+ beforeEach('set next block time when operation expired', async function () {
+ this.scheduledAt = await time.clock.timestamp();
+ const schedule = await this.manager.getSchedule(this.operationId);
+ await time.increaseTo.timestamp(schedule + EXPIRATION, !!expired.mineDelay);
+ });
+
+ expired();
+ });
+ });
+
+ describe('when operation is not scheduled', function () {
+ beforeEach('set expected operationId', async function () {
+ this.operationId = await this.manager.hashOperation(this.caller, this.target, this.calldata);
+
+ // Assert operation is not scheduled
+ expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
+ });
+
+ notScheduled();
+ });
+}
+
+/**
+ * @requires this.{manager,roles,target,calldata}
+ */
+function testAsRestrictedOperation({ callerIsTheManager: { executing, notExecuting }, callerIsNotTheManager }) {
+ describe('when the call comes from the manager (msg.sender == manager)', function () {
+ beforeEach('define caller as manager', async function () {
+ this.caller = this.manager;
+ if (this.caller.target) {
+ await impersonate(this.caller.target);
+ this.caller = await ethers.getSigner(this.caller.target);
+ }
+ });
+
+ describe('when _executionId is in storage for target and selector', function () {
+ beforeEach('set _executionId flag from calldata and target', async function () {
+ const executionId = ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(
+ ['address', 'bytes4'],
+ [this.target.target, this.calldata.substring(0, 10)],
+ ),
+ );
+ await setStorageAt(this.manager.target, EXECUTION_ID_STORAGE_SLOT, executionId);
+ });
+
+ executing();
+ });
+
+ describe('when _executionId does not match target and selector', notExecuting);
+ });
+
+ describe('when the call does not come from the manager (msg.sender != manager)', function () {
+ beforeEach('define non manager caller', function () {
+ this.caller = this.roles.SOME.members[0];
+ });
+
+ callerIsNotTheManager();
+ });
+}
+
+/**
+ * @requires this.{manager,scheduleIn,caller,target,calldata,executionDelay}
+ */
+function testAsDelayedOperation() {
+ describe('with operation delay', function () {
+ describe('when operation delay is greater than execution delay', function () {
+ beforeEach('set operation delay', async function () {
+ this.operationDelay = this.executionDelay + time.duration.hours(1);
+ await this.manager.$_setTargetAdminDelay(this.target, this.operationDelay);
+ this.scheduleIn = this.operationDelay; // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ });
+
+ describe('when operation delay is shorter than execution delay', function () {
+ beforeEach('set operation delay', async function () {
+ this.operationDelay = this.executionDelay - time.duration.hours(1);
+ await this.manager.$_setTargetAdminDelay(this.target, this.operationDelay);
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ });
+ });
+
+ describe('without operation delay', function () {
+ beforeEach('set operation delay', async function () {
+ this.operationDelay = 0n;
+ await this.manager.$_setTargetAdminDelay(this.target, this.operationDelay);
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ });
+}
+
+// ============ METHOD ============
+
+/**
+ * @requires this.{manager,roles,role,target,calldata}
+ */
+function testAsCanCall({
+ closed,
+ open: {
+ callerIsTheManager,
+ callerIsNotTheManager: { publicRoleIsRequired, specificRoleIsRequired },
+ },
+}) {
+ testAsClosable({
+ closed,
+ open() {
+ testAsRestrictedOperation({
+ callerIsTheManager,
+ callerIsNotTheManager() {
+ testAsHasRole({
+ publicRoleIsRequired,
+ specificRoleIsRequired,
+ });
+ },
+ });
+ },
+ });
+}
+
+/**
+ * @requires this.{target,calldata,roles,role}
+ */
+function testAsHasRole({ publicRoleIsRequired, specificRoleIsRequired }) {
+ describe('when the function requires the caller to be granted with the PUBLIC_ROLE', function () {
+ beforeEach('set target function role as PUBLIC_ROLE', async function () {
+ this.role = this.roles.PUBLIC;
+ await this.manager
+ .connect(this.roles.ADMIN.members[0])
+ .$_setTargetFunctionRole(this.target, this.calldata.substring(0, 10), this.role.id);
+ });
+
+ publicRoleIsRequired();
+ });
+
+ describe('when the function requires the caller to be granted with a role other than PUBLIC_ROLE', function () {
+ beforeEach('set target function role as PUBLIC_ROLE', async function () {
+ await this.manager
+ .connect(this.roles.ADMIN.members[0])
+ .$_setTargetFunctionRole(this.target, this.calldata.substring(0, 10), this.role.id);
+ });
+
+ testAsGetAccess(specificRoleIsRequired);
+ });
+}
+
+/**
+ * @requires this.{manager,role,caller}
+ */
+function testAsGetAccess({
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ // Because both grant and execution delay are set within the same $_grantRole call
+ // it's not possible to create a set of tests that diverge between grant and execution delay.
+ // Therefore, the testAsDelay arguments are renamed for clarity:
+ // before => beforeGrantDelay
+ // after => afterGrantDelay
+ callerHasAnExecutionDelay: { beforeGrantDelay: case1, afterGrantDelay: case2 },
+ callerHasNoExecutionDelay: { beforeGrantDelay: case3, afterGrantDelay: case4 },
+ },
+ roleGrantingIsNotDelayed: { callerHasAnExecutionDelay: case5, callerHasNoExecutionDelay: case6 },
+ },
+ requiredRoleIsNotGranted,
+}) {
+ describe('when the required role is granted to the caller', function () {
+ describe('when role granting is delayed', function () {
+ beforeEach('define delay', function () {
+ this.grantDelay = time.duration.minutes(3);
+ this.delay = this.grantDelay; // For testAsDelay
+ });
+
+ describe('when caller has an execution delay', function () {
+ beforeEach('set role and delay', async function () {
+ this.executionDelay = time.duration.hours(10);
+ this.delay = this.grantDelay;
+ await this.manager.$_grantRole(this.role.id, this.caller, this.grantDelay, this.executionDelay);
+ });
+
+ testAsDelay('grant', { before: case1, after: case2 });
+ });
+
+ describe('when caller has no execution delay', function () {
+ beforeEach('set role and delay', async function () {
+ this.executionDelay = 0n;
+ await this.manager.$_grantRole(this.role.id, this.caller, this.grantDelay, this.executionDelay);
+ });
+
+ testAsDelay('grant', { before: case3, after: case4 });
+ });
+ });
+
+ describe('when role granting is not delayed', function () {
+ beforeEach('define delay', function () {
+ this.grantDelay = 0n;
+ });
+
+ describe('when caller has an execution delay', function () {
+ beforeEach('set role and delay', async function () {
+ this.executionDelay = time.duration.hours(10);
+ await this.manager.$_grantRole(this.role.id, this.caller, this.grantDelay, this.executionDelay);
+ });
+
+ case5();
+ });
+
+ describe('when caller has no execution delay', function () {
+ beforeEach('set role and delay', async function () {
+ this.executionDelay = 0n;
+ await this.manager.$_grantRole(this.role.id, this.caller, this.grantDelay, this.executionDelay);
+ });
+
+ case6();
+ });
+ });
+ });
+
+ describe('when role is not granted', function () {
+ // Because this helper can be composed with other helpers, it's possible
+ // that role has been set already by another helper.
+ // Although this is highly unlikely, we check for it here to avoid false positives.
+ beforeEach('assert role is unset', async function () {
+ const { since } = await this.manager.getAccess(this.role.id, this.caller);
+ expect(since).to.equal(0n);
+ });
+
+ requiredRoleIsNotGranted();
+ });
+}
+
+module.exports = {
+ LIKE_COMMON_IS_EXECUTING,
+ LIKE_COMMON_GET_ACCESS,
+ LIKE_COMMON_SCHEDULABLE,
+ testAsClosable,
+ testAsDelay,
+ testAsSchedulableOperation,
+ testAsRestrictedOperation,
+ testAsDelayedOperation,
+ testAsCanCall,
+ testAsHasRole,
+ testAsGetAccess,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.test.js
new file mode 100644
index 000000000..7726831b2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AccessManager.test.js
@@ -0,0 +1,2489 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { impersonate } = require('../../helpers/account');
+const { MAX_UINT48 } = require('../../helpers/constants');
+const { selector } = require('../../helpers/methods');
+const time = require('../../helpers/time');
+
+const {
+ buildBaseRoles,
+ formatAccess,
+ EXPIRATION,
+ MINSETBACK,
+ EXECUTION_ID_STORAGE_SLOT,
+ CONSUMING_SCHEDULE_STORAGE_SLOT,
+ prepareOperation,
+ hashOperation,
+} = require('../../helpers/access-manager');
+
+const {
+ shouldBehaveLikeDelayedAdminOperation,
+ shouldBehaveLikeNotDelayedAdminOperation,
+ shouldBehaveLikeRoleAdminOperation,
+ shouldBehaveLikeAManagedRestrictedOperation,
+ shouldBehaveLikeASelfRestrictedOperation,
+} = require('./AccessManager.behavior');
+
+const {
+ LIKE_COMMON_SCHEDULABLE,
+ testAsClosable,
+ testAsDelay,
+ testAsSchedulableOperation,
+ testAsCanCall,
+ testAsHasRole,
+ testAsGetAccess,
+} = require('./AccessManager.predicate');
+
+async function fixture() {
+ const [admin, roleAdmin, roleGuardian, member, user, other] = await ethers.getSigners();
+
+ // Build roles
+ const roles = buildBaseRoles();
+
+ // Add members
+ roles.ADMIN.members = [admin];
+ roles.SOME_ADMIN.members = [roleAdmin];
+ roles.SOME_GUARDIAN.members = [roleGuardian];
+ roles.SOME.members = [member];
+ roles.PUBLIC.members = [admin, roleAdmin, roleGuardian, member, user, other];
+
+ const manager = await ethers.deployContract('$AccessManagerMock', [admin]);
+ const target = await ethers.deployContract('$AccessManagedTarget', [manager]);
+
+ for (const { id: roleId, admin, guardian, members } of Object.values(roles)) {
+ if (roleId === roles.PUBLIC.id) continue; // Every address belong to public and is locked
+ if (roleId === roles.ADMIN.id) continue; // Admin set during construction and is locked
+
+ // Set admin role avoiding default
+ if (admin.id !== roles.ADMIN.id) {
+ await manager.$_setRoleAdmin(roleId, admin.id);
+ }
+
+ // Set guardian role avoiding default
+ if (guardian.id !== roles.ADMIN.id) {
+ await manager.$_setRoleGuardian(roleId, guardian.id);
+ }
+
+ // Grant role to members
+ for (const member of members) {
+ await manager.$_grantRole(roleId, member, 0, 0);
+ }
+ }
+
+ return {
+ admin,
+ roleAdmin,
+ user,
+ other,
+ roles,
+ manager,
+ target,
+ };
+}
+
+// This test suite is made using the following tools:
+//
+// * Predicates: Functions with common conditional setups without assertions.
+// * Behaviors: Functions with common assertions.
+//
+// The behavioral tests are built by composing predicates and are used as templates
+// for testing access to restricted functions.
+//
+// Similarly, unit tests in this suite will use predicates to test subsets of these
+// behaviors and are helped by common assertions provided for some of the predicates.
+//
+// The predicates can be identified by the `testAs*` prefix while the behaviors
+// are prefixed with `shouldBehave*`. The common assertions for predicates are
+// defined as constants.
+describe('AccessManager', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('during construction', function () {
+ it('grants admin role to initialAdmin', async function () {
+ const manager = await ethers.deployContract('$AccessManager', [this.other]);
+ expect(await manager.hasRole(this.roles.ADMIN.id, this.other).then(formatAccess)).to.be.deep.equal([true, '0']);
+ });
+
+ it('rejects zero address for initialAdmin', async function () {
+ await expect(ethers.deployContract('$AccessManager', [ethers.ZeroAddress]))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerInvalidInitialAdmin')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('initializes setup roles correctly', async function () {
+ for (const { id: roleId, admin, guardian, members } of Object.values(this.roles)) {
+ expect(await this.manager.getRoleAdmin(roleId)).to.equal(admin.id);
+ expect(await this.manager.getRoleGuardian(roleId)).to.equal(guardian.id);
+
+ for (const user of this.roles.PUBLIC.members) {
+ expect(await this.manager.hasRole(roleId, user).then(formatAccess)).to.be.deep.equal([
+ members.includes(user),
+ '0',
+ ]);
+ }
+ }
+ });
+ });
+
+ describe('getters', function () {
+ describe('#canCall', function () {
+ beforeEach('set calldata', function () {
+ this.calldata = '0x12345678';
+ this.role = { id: 379204n };
+ });
+
+ testAsCanCall({
+ closed() {
+ it('should return false and no delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.other,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ },
+ open: {
+ callerIsTheManager: {
+ executing() {
+ it('should return true and no delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.true;
+ expect(delay).to.equal(0n);
+ });
+ },
+ notExecuting() {
+ it('should return false and no delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ },
+ },
+ callerIsNotTheManager: {
+ publicRoleIsRequired() {
+ it('should return true and no delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.true;
+ expect(delay).to.equal(0n);
+ });
+ },
+ specificRoleIsRequired: {
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ callerHasAnExecutionDelay: {
+ beforeGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('should return false and no execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ beforeEach('sets execution delay', function () {
+ this.scheduleIn = this.executionDelay; // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation({
+ scheduled: {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('should return false and execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(this.executionDelay);
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('should return false and execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(this.executionDelay);
+ });
+ },
+ expired: function self() {
+ self.mineDelay = true;
+
+ it('should return false and execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(this.executionDelay);
+ });
+ },
+ },
+ notScheduled() {
+ it('should return false and execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(this.executionDelay);
+ });
+ },
+ });
+ },
+ },
+ callerHasNoExecutionDelay: {
+ beforeGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('should return false and no execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('should return true and no execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.true;
+ expect(delay).to.equal(0n);
+ });
+ },
+ },
+ },
+ roleGrantingIsNotDelayed: {
+ callerHasAnExecutionDelay() {
+ it('should return false and execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(this.executionDelay);
+ });
+ },
+ callerHasNoExecutionDelay() {
+ it('should return true and no execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.true;
+ expect(delay).to.equal(0n);
+ });
+ },
+ },
+ },
+ requiredRoleIsNotGranted() {
+ it('should return false and no execution delay', async function () {
+ const { immediate, delay } = await this.manager.canCall(
+ this.caller,
+ this.target,
+ this.calldata.substring(0, 10),
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ },
+ },
+ },
+ },
+ });
+ });
+
+ describe('#expiration', function () {
+ it('has a 7 days default expiration', async function () {
+ expect(await this.manager.expiration()).to.equal(EXPIRATION);
+ });
+ });
+
+ describe('#minSetback', function () {
+ it('has a 5 days default minimum setback', async function () {
+ expect(await this.manager.minSetback()).to.equal(MINSETBACK);
+ });
+ });
+
+ describe('#isTargetClosed', function () {
+ testAsClosable({
+ closed() {
+ it('returns true', async function () {
+ expect(await this.manager.isTargetClosed(this.target)).to.be.true;
+ });
+ },
+ open() {
+ it('returns false', async function () {
+ expect(await this.manager.isTargetClosed(this.target)).to.be.false;
+ });
+ },
+ });
+ });
+
+ describe('#getTargetFunctionRole', function () {
+ const methodSelector = selector('something(address,bytes)');
+
+ it('returns the target function role', async function () {
+ const roleId = 21498n;
+ await this.manager.$_setTargetFunctionRole(this.target, methodSelector, roleId);
+
+ expect(await this.manager.getTargetFunctionRole(this.target, methodSelector)).to.equal(roleId);
+ });
+
+ it('returns the ADMIN role if not set', async function () {
+ expect(await this.manager.getTargetFunctionRole(this.target, methodSelector)).to.equal(this.roles.ADMIN.id);
+ });
+ });
+
+ describe('#getTargetAdminDelay', function () {
+ describe('when the target admin delay is setup', function () {
+ beforeEach('set target admin delay', async function () {
+ this.oldDelay = await this.manager.getTargetAdminDelay(this.target);
+ this.newDelay = time.duration.days(10);
+
+ await this.manager.$_setTargetAdminDelay(this.target, this.newDelay);
+ this.delay = MINSETBACK; // For testAsDelay
+ });
+
+ testAsDelay('effect', {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('returns the old target admin delay', async function () {
+ expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(this.oldDelay);
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('returns the new target admin delay', async function () {
+ expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(this.newDelay);
+ });
+ },
+ });
+ });
+
+ it('returns the 0 if not set', async function () {
+ expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(0n);
+ });
+ });
+
+ describe('#getRoleAdmin', function () {
+ const roleId = 5234907n;
+
+ it('returns the role admin', async function () {
+ const adminId = 789433n;
+
+ await this.manager.$_setRoleAdmin(roleId, adminId);
+
+ expect(await this.manager.getRoleAdmin(roleId)).to.equal(adminId);
+ });
+
+ it('returns the ADMIN role if not set', async function () {
+ expect(await this.manager.getRoleAdmin(roleId)).to.equal(this.roles.ADMIN.id);
+ });
+ });
+
+ describe('#getRoleGuardian', function () {
+ const roleId = 5234907n;
+
+ it('returns the role guardian', async function () {
+ const guardianId = 789433n;
+
+ await this.manager.$_setRoleGuardian(roleId, guardianId);
+
+ expect(await this.manager.getRoleGuardian(roleId)).to.equal(guardianId);
+ });
+
+ it('returns the ADMIN role if not set', async function () {
+ expect(await this.manager.getRoleGuardian(roleId)).to.equal(this.roles.ADMIN.id);
+ });
+ });
+
+ describe('#getRoleGrantDelay', function () {
+ const roleId = 9248439n;
+
+ describe('when the grant admin delay is setup', function () {
+ beforeEach('set grant admin delay', async function () {
+ this.oldDelay = await this.manager.getRoleGrantDelay(roleId);
+ this.newDelay = time.duration.days(11);
+
+ await this.manager.$_setGrantDelay(roleId, this.newDelay);
+ this.delay = MINSETBACK; // For testAsDelay
+ });
+
+ testAsDelay('grant', {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('returns the old role grant delay', async function () {
+ expect(await this.manager.getRoleGrantDelay(roleId)).to.equal(this.oldDelay);
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('returns the new role grant delay', async function () {
+ expect(await this.manager.getRoleGrantDelay(roleId)).to.equal(this.newDelay);
+ });
+ },
+ });
+ });
+
+ it('returns 0 if delay is not set', async function () {
+ expect(await this.manager.getTargetAdminDelay(this.target)).to.equal(0n);
+ });
+ });
+
+ describe('#getAccess', function () {
+ beforeEach('set role', function () {
+ this.role = { id: 9452n };
+ this.caller = this.user;
+ });
+
+ testAsGetAccess({
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ callerHasAnExecutionDelay: {
+ beforeGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('role is not in effect and execution delay is set', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+ expect(access[0]).to.equal(this.delayEffect); // inEffectSince
+ expect(access[1]).to.equal(this.executionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Not in effect yet
+ expect(await time.clock.timestamp()).to.lt(access[0]);
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('access has role in effect and execution delay is set', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+
+ expect(access[0]).to.equal(this.delayEffect); // inEffectSince
+ expect(access[1]).to.equal(this.executionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await time.clock.timestamp()).to.equal(access[0]);
+ });
+ },
+ },
+ callerHasNoExecutionDelay: {
+ beforeGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('access has role not in effect without execution delay', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+ expect(access[0]).to.equal(this.delayEffect); // inEffectSince
+ expect(access[1]).to.equal(0n); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Not in effect yet
+ expect(await time.clock.timestamp()).to.lt(access[0]);
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('role is in effect without execution delay', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+ expect(access[0]).to.equal(this.delayEffect); // inEffectSince
+ expect(access[1]).to.equal(0n); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await time.clock.timestamp()).to.equal(access[0]);
+ });
+ },
+ },
+ },
+ roleGrantingIsNotDelayed: {
+ callerHasAnExecutionDelay() {
+ it('access has role in effect and execution delay is set', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+ expect(access[0]).to.equal(await time.clock.timestamp()); // inEffectSince
+ expect(access[1]).to.equal(this.executionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await time.clock.timestamp()).to.equal(access[0]);
+ });
+ },
+ callerHasNoExecutionDelay() {
+ it('access has role in effect without execution delay', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+ expect(access[0]).to.equal(await time.clock.timestamp()); // inEffectSince
+ expect(access[1]).to.equal(0n); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await time.clock.timestamp()).to.equal(access[0]);
+ });
+ },
+ },
+ },
+ requiredRoleIsNotGranted() {
+ it('has empty access', async function () {
+ const access = await this.manager.getAccess(this.role.id, this.caller);
+ expect(access[0]).to.equal(0n); // inEffectSince
+ expect(access[1]).to.equal(0n); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+ });
+ },
+ });
+ });
+
+ describe('#hasRole', function () {
+ beforeEach('setup testAsHasRole', function () {
+ this.role = { id: 49832n };
+ this.calldata = '0x12345678';
+ this.caller = this.user;
+ });
+
+ testAsHasRole({
+ publicRoleIsRequired() {
+ it('has PUBLIC role', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.true;
+ expect(executionDelay).to.equal('0');
+ });
+ },
+ specificRoleIsRequired: {
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ callerHasAnExecutionDelay: {
+ beforeGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('does not have role but execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.false;
+ expect(executionDelay).to.equal(this.executionDelay);
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('has role and execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.true;
+ expect(executionDelay).to.equal(this.executionDelay);
+ });
+ },
+ },
+ callerHasNoExecutionDelay: {
+ beforeGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('does not have role nor execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.false;
+ expect(executionDelay).to.equal('0');
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('has role and no execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.true;
+ expect(executionDelay).to.equal('0');
+ });
+ },
+ },
+ },
+ roleGrantingIsNotDelayed: {
+ callerHasAnExecutionDelay() {
+ it('has role and execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.true;
+ expect(executionDelay).to.equal(this.executionDelay);
+ });
+ },
+ callerHasNoExecutionDelay() {
+ it('has role and no execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.true;
+ expect(executionDelay).to.equal('0');
+ });
+ },
+ },
+ },
+ requiredRoleIsNotGranted() {
+ it('has no role and no execution delay', async function () {
+ const { isMember, executionDelay } = await this.manager.hasRole(this.role.id, this.caller);
+ expect(isMember).to.be.false;
+ expect(executionDelay).to.equal('0');
+ });
+ },
+ },
+ });
+ });
+
+ describe('#getSchedule', function () {
+ beforeEach('set role and calldata', async function () {
+ const fnRestricted = this.target.fnRestricted.getFragment().selector;
+ this.caller = this.user;
+ this.role = { id: 493590n };
+ await this.manager.$_setTargetFunctionRole(this.target, fnRestricted, this.role.id);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
+
+ this.calldata = this.target.interface.encodeFunctionData(fnRestricted, []);
+ this.scheduleIn = time.duration.days(10); // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation({
+ scheduled: {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('returns schedule in the future', async function () {
+ const schedule = await this.manager.getSchedule(this.operationId);
+ expect(schedule).to.equal(this.scheduledAt + this.scheduleIn);
+ expect(schedule).to.gt(await time.clock.timestamp());
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('returns schedule', async function () {
+ const schedule = await this.manager.getSchedule(this.operationId);
+ expect(schedule).to.equal(this.scheduledAt + this.scheduleIn);
+ expect(schedule).to.equal(await time.clock.timestamp());
+ });
+ },
+ expired: function self() {
+ self.mineDelay = true;
+
+ it('returns 0', async function () {
+ expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
+ });
+ },
+ },
+ notScheduled() {
+ it('defaults to 0', async function () {
+ expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
+ });
+ },
+ });
+ });
+
+ describe('#getNonce', function () {
+ describe('when operation is scheduled', function () {
+ beforeEach('schedule operation', async function () {
+ const fnRestricted = this.target.fnRestricted.getFragment().selector;
+ this.caller = this.user;
+ this.role = { id: 4209043n };
+ await this.manager.$_setTargetFunctionRole(this.target, fnRestricted, this.role.id);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
+
+ this.calldata = this.target.interface.encodeFunctionData(fnRestricted, []);
+ this.delay = time.duration.days(10);
+
+ const { operationId, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+ await schedule();
+ this.operationId = operationId;
+ });
+
+ it('returns nonce', async function () {
+ expect(await this.manager.getNonce(this.operationId)).to.equal(1n);
+ });
+ });
+
+ describe('when is not scheduled', function () {
+ it('returns default 0', async function () {
+ expect(await this.manager.getNonce(ethers.id('operation'))).to.equal(0n);
+ });
+ });
+ });
+
+ describe('#hashOperation', function () {
+ it('returns an operationId', async function () {
+ const args = [this.user, this.other, '0x123543'];
+ expect(await this.manager.hashOperation(...args)).to.equal(hashOperation(...args));
+ });
+ });
+ });
+
+ describe('admin operations', function () {
+ beforeEach('set required role', function () {
+ this.role = this.roles.ADMIN;
+ });
+
+ describe('subject to a delay', function () {
+ describe('#labelRole', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [123443, 'TEST'];
+ const method = this.manager.interface.getFunction('labelRole(uint64,string)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeDelayedAdminOperation();
+ });
+
+ it('emits an event with the label', async function () {
+ await expect(this.manager.connect(this.admin).labelRole(this.roles.SOME.id, 'Some label'))
+ .to.emit(this.manager, 'RoleLabel')
+ .withArgs(this.roles.SOME.id, 'Some label');
+ });
+
+ it('updates label on a second call', async function () {
+ await this.manager.connect(this.admin).labelRole(this.roles.SOME.id, 'Some label');
+
+ await expect(this.manager.connect(this.admin).labelRole(this.roles.SOME.id, 'Updated label'))
+ .to.emit(this.manager, 'RoleLabel')
+ .withArgs(this.roles.SOME.id, 'Updated label');
+ });
+
+ it('reverts labeling PUBLIC_ROLE', async function () {
+ await expect(this.manager.connect(this.admin).labelRole(this.roles.PUBLIC.id, 'Some label'))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+
+ it('reverts labeling ADMIN_ROLE', async function () {
+ await expect(this.manager.connect(this.admin).labelRole(this.roles.ADMIN.id, 'Some label'))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.ADMIN.id);
+ });
+ });
+
+ describe('#setRoleAdmin', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [93445, 84532];
+ const method = this.manager.interface.getFunction('setRoleAdmin(uint64,uint64)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeDelayedAdminOperation();
+ });
+
+ it("sets any role's admin if called by an admin", async function () {
+ expect(await this.manager.getRoleAdmin(this.roles.SOME.id)).to.equal(this.roles.SOME_ADMIN.id);
+
+ await expect(this.manager.connect(this.admin).setRoleAdmin(this.roles.SOME.id, this.roles.ADMIN.id))
+ .to.emit(this.manager, 'RoleAdminChanged')
+ .withArgs(this.roles.SOME.id, this.roles.ADMIN.id);
+
+ expect(await this.manager.getRoleAdmin(this.roles.SOME.id)).to.equal(this.roles.ADMIN.id);
+ });
+
+ it('reverts setting PUBLIC_ROLE admin', async function () {
+ await expect(this.manager.connect(this.admin).setRoleAdmin(this.roles.PUBLIC.id, this.roles.ADMIN.id))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+
+ it('reverts setting ADMIN_ROLE admin', async function () {
+ await expect(this.manager.connect(this.admin).setRoleAdmin(this.roles.ADMIN.id, this.roles.ADMIN.id))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.ADMIN.id);
+ });
+ });
+
+ describe('#setRoleGuardian', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [93445, 84532];
+ const method = this.manager.interface.getFunction('setRoleGuardian(uint64,uint64)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeDelayedAdminOperation();
+ });
+
+ it("sets any role's guardian if called by an admin", async function () {
+ expect(await this.manager.getRoleGuardian(this.roles.SOME.id)).to.equal(this.roles.SOME_GUARDIAN.id);
+
+ await expect(this.manager.connect(this.admin).setRoleGuardian(this.roles.SOME.id, this.roles.ADMIN.id))
+ .to.emit(this.manager, 'RoleGuardianChanged')
+ .withArgs(this.roles.SOME.id, this.roles.ADMIN.id);
+
+ expect(await this.manager.getRoleGuardian(this.roles.SOME.id)).to.equal(this.roles.ADMIN.id);
+ });
+
+ it('reverts setting PUBLIC_ROLE admin', async function () {
+ await expect(this.manager.connect(this.admin).setRoleGuardian(this.roles.PUBLIC.id, this.roles.ADMIN.id))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+
+ it('reverts setting ADMIN_ROLE admin', async function () {
+ await expect(this.manager.connect(this.admin).setRoleGuardian(this.roles.ADMIN.id, this.roles.ADMIN.id))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.ADMIN.id);
+ });
+ });
+
+ describe('#setGrantDelay', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [984910, time.duration.days(2)];
+ const method = this.manager.interface.getFunction('setGrantDelay(uint64,uint32)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeDelayedAdminOperation();
+ });
+
+ it('reverts setting grant delay for the PUBLIC_ROLE', async function () {
+ await expect(this.manager.connect(this.admin).setGrantDelay(this.roles.PUBLIC.id, 69n))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+
+ describe('when increasing the delay', function () {
+ const oldDelay = 10n;
+ const newDelay = 100n;
+
+ beforeEach('sets old delay', async function () {
+ this.role = this.roles.SOME;
+ await this.manager.$_setGrantDelay(this.role.id, oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
+ });
+
+ it('increases the delay after minsetback', async function () {
+ const txResponse = await this.manager.connect(this.admin).setGrantDelay(this.role.id, newDelay);
+ const setGrantDelayAt = await time.clockFromReceipt.timestamp(txResponse);
+ await expect(txResponse)
+ .to.emit(this.manager, 'RoleGrantDelayChanged')
+ .withArgs(this.role.id, newDelay, setGrantDelayAt + MINSETBACK);
+
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(newDelay);
+ });
+ });
+
+ describe('when reducing the delay', function () {
+ const oldDelay = time.duration.days(10);
+
+ beforeEach('sets old delay', async function () {
+ this.role = this.roles.SOME;
+ await this.manager.$_setGrantDelay(this.role.id, oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
+ });
+
+ describe('when the delay difference is shorter than minimum setback', function () {
+ const newDelay = oldDelay - 1n;
+
+ it('increases the delay after minsetback', async function () {
+ const txResponse = await this.manager.connect(this.admin).setGrantDelay(this.role.id, newDelay);
+ const setGrantDelayAt = await time.clockFromReceipt.timestamp(txResponse);
+ await expect(txResponse)
+ .to.emit(this.manager, 'RoleGrantDelayChanged')
+ .withArgs(this.role.id, newDelay, setGrantDelayAt + MINSETBACK);
+
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(newDelay);
+ });
+ });
+
+ describe('when the delay difference is longer than minimum setback', function () {
+ const newDelay = 1n;
+
+ beforeEach('assert delay difference is higher than minsetback', function () {
+ expect(oldDelay - newDelay).to.gt(MINSETBACK);
+ });
+
+ it('increases the delay after delay difference', async function () {
+ const setback = oldDelay - newDelay;
+
+ const txResponse = await this.manager.connect(this.admin).setGrantDelay(this.role.id, newDelay);
+ const setGrantDelayAt = await time.clockFromReceipt.timestamp(txResponse);
+
+ await expect(txResponse)
+ .to.emit(this.manager, 'RoleGrantDelayChanged')
+ .withArgs(this.role.id, newDelay, setGrantDelayAt + setback);
+
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(oldDelay);
+ await time.increaseBy.timestamp(setback);
+ expect(await this.manager.getRoleGrantDelay(this.role.id)).to.equal(newDelay);
+ });
+ });
+ });
+ });
+
+ describe('#setTargetAdminDelay', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [this.other.address, time.duration.days(3)];
+ const method = this.manager.interface.getFunction('setTargetAdminDelay(address,uint32)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeDelayedAdminOperation();
+ });
+
+ describe('when increasing the delay', function () {
+ const oldDelay = time.duration.days(10);
+ const newDelay = time.duration.days(11);
+
+ beforeEach('sets old delay', async function () {
+ await this.manager.$_setTargetAdminDelay(this.other, oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
+ });
+
+ it('increases the delay after minsetback', async function () {
+ const txResponse = await this.manager.connect(this.admin).setTargetAdminDelay(this.other, newDelay);
+ const setTargetAdminDelayAt = await time.clockFromReceipt.timestamp(txResponse);
+ await expect(txResponse)
+ .to.emit(this.manager, 'TargetAdminDelayUpdated')
+ .withArgs(this.other, newDelay, setTargetAdminDelayAt + MINSETBACK);
+
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(newDelay);
+ });
+ });
+
+ describe('when reducing the delay', function () {
+ const oldDelay = time.duration.days(10);
+
+ beforeEach('sets old delay', async function () {
+ await this.manager.$_setTargetAdminDelay(this.other, oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
+ });
+
+ describe('when the delay difference is shorter than minimum setback', function () {
+ const newDelay = oldDelay - 1n;
+
+ it('increases the delay after minsetback', async function () {
+ const txResponse = await this.manager.connect(this.admin).setTargetAdminDelay(this.other, newDelay);
+ const setTargetAdminDelayAt = await time.clockFromReceipt.timestamp(txResponse);
+ await expect(txResponse)
+ .to.emit(this.manager, 'TargetAdminDelayUpdated')
+ .withArgs(this.other, newDelay, setTargetAdminDelayAt + MINSETBACK);
+
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(newDelay);
+ });
+ });
+
+ describe('when the delay difference is longer than minimum setback', function () {
+ const newDelay = 1n;
+
+ beforeEach('assert delay difference is higher than minsetback', function () {
+ expect(oldDelay - newDelay).to.gt(MINSETBACK);
+ });
+
+ it('increases the delay after delay difference', async function () {
+ const setback = oldDelay - newDelay;
+
+ const txResponse = await this.manager.connect(this.admin).setTargetAdminDelay(this.other, newDelay);
+ const setTargetAdminDelayAt = await time.clockFromReceipt.timestamp(txResponse);
+
+ await expect(txResponse)
+ .to.emit(this.manager, 'TargetAdminDelayUpdated')
+ .withArgs(this.other, newDelay, setTargetAdminDelayAt + setback);
+
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(oldDelay);
+ await time.increaseBy.timestamp(setback);
+ expect(await this.manager.getTargetAdminDelay(this.other)).to.equal(newDelay);
+ });
+ });
+ });
+ });
+ });
+
+ describe('not subject to a delay', function () {
+ describe('#updateAuthority', function () {
+ beforeEach('create a target and a new authority', async function () {
+ this.newAuthority = await ethers.deployContract('$AccessManager', [this.admin]);
+ this.newManagedTarget = await ethers.deployContract('$AccessManagedTarget', [this.manager]);
+ });
+
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ this.calldata = this.manager.interface.encodeFunctionData('updateAuthority(address,address)', [
+ this.newManagedTarget.target,
+ this.newAuthority.target,
+ ]);
+ });
+
+ shouldBehaveLikeNotDelayedAdminOperation();
+ });
+
+ it('changes the authority', async function () {
+ expect(await this.newManagedTarget.authority()).to.equal(this.manager);
+
+ await expect(this.manager.connect(this.admin).updateAuthority(this.newManagedTarget, this.newAuthority))
+ .to.emit(this.newManagedTarget, 'AuthorityUpdated') // Managed contract is responsible of notifying the change through an event
+ .withArgs(this.newAuthority);
+
+ expect(await this.newManagedTarget.authority()).to.equal(this.newAuthority);
+ });
+ });
+
+ describe('#setTargetClosed', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [this.other.address, true];
+ const method = this.manager.interface.getFunction('setTargetClosed(address,bool)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeNotDelayedAdminOperation();
+ });
+
+ it('closes and opens a target', async function () {
+ await expect(this.manager.connect(this.admin).setTargetClosed(this.target, true))
+ .to.emit(this.manager, 'TargetClosed')
+ .withArgs(this.target, true);
+ expect(await this.manager.isTargetClosed(this.target)).to.be.true;
+
+ await expect(this.manager.connect(this.admin).setTargetClosed(this.target, false))
+ .to.emit(this.manager, 'TargetClosed')
+ .withArgs(this.target, false);
+ expect(await this.manager.isTargetClosed(this.target)).to.be.false;
+ });
+
+ describe('when the target is the manager', async function () {
+ it('closes and opens the manager', async function () {
+ await expect(this.manager.connect(this.admin).setTargetClosed(this.manager, true))
+ .to.emit(this.manager, 'TargetClosed')
+ .withArgs(this.manager, true);
+ expect(await this.manager.isTargetClosed(this.manager)).to.be.true;
+
+ await expect(this.manager.connect(this.admin).setTargetClosed(this.manager, false))
+ .to.emit(this.manager, 'TargetClosed')
+ .withArgs(this.manager, false);
+ expect(await this.manager.isTargetClosed(this.manager)).to.be.false;
+ });
+ });
+ });
+
+ describe('#setTargetFunctionRole', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [this.other.address, ['0x12345678'], 443342];
+ const method = this.manager.interface.getFunction('setTargetFunctionRole(address,bytes4[],uint64)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeNotDelayedAdminOperation();
+ });
+
+ const sigs = ['someFunction()', 'someOtherFunction(uint256)', 'oneMoreFunction(address,uint8)'].map(selector);
+
+ it('sets function roles', async function () {
+ for (const sig of sigs) {
+ expect(await this.manager.getTargetFunctionRole(this.target, sig)).to.equal(this.roles.ADMIN.id);
+ }
+
+ const allowRole = await this.manager
+ .connect(this.admin)
+ .setTargetFunctionRole(this.target, sigs, this.roles.SOME.id);
+
+ for (const sig of sigs) {
+ await expect(allowRole)
+ .to.emit(this.manager, 'TargetFunctionRoleUpdated')
+ .withArgs(this.target, sig, this.roles.SOME.id);
+ expect(await this.manager.getTargetFunctionRole(this.target, sig)).to.equal(this.roles.SOME.id);
+ }
+
+ await expect(
+ this.manager.connect(this.admin).setTargetFunctionRole(this.target, [sigs[1]], this.roles.SOME_ADMIN.id),
+ )
+ .to.emit(this.manager, 'TargetFunctionRoleUpdated')
+ .withArgs(this.target, sigs[1], this.roles.SOME_ADMIN.id);
+
+ for (const sig of sigs) {
+ expect(await this.manager.getTargetFunctionRole(this.target, sig)).to.equal(
+ sig == sigs[1] ? this.roles.SOME_ADMIN.id : this.roles.SOME.id,
+ );
+ }
+ });
+ });
+
+ describe('role admin operations', function () {
+ const ANOTHER_ADMIN = 0xdeadc0de1n;
+ const ANOTHER_ROLE = 0xdeadc0de2n;
+
+ beforeEach('set required role', async function () {
+ // Make admin a member of ANOTHER_ADMIN
+ await this.manager.$_grantRole(ANOTHER_ADMIN, this.admin, 0, 0);
+ await this.manager.$_setRoleAdmin(ANOTHER_ROLE, ANOTHER_ADMIN);
+
+ this.role = { id: ANOTHER_ADMIN };
+ await this.manager.$_grantRole(this.role.id, this.user, 0, 0);
+ });
+
+ describe('#grantRole', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ const args = [ANOTHER_ROLE, this.other.address, 0];
+ const method = this.manager.interface.getFunction('grantRole(uint64,address,uint32)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+ });
+
+ shouldBehaveLikeRoleAdminOperation(ANOTHER_ADMIN);
+ });
+
+ it('reverts when granting PUBLIC_ROLE', async function () {
+ await expect(this.manager.connect(this.admin).grantRole(this.roles.PUBLIC.id, this.user, 0))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+
+ describe('when the user is not a role member', function () {
+ describe('with grant delay', function () {
+ beforeEach('set grant delay and grant role', async function () {
+ // Delay granting
+ this.grantDelay = time.duration.weeks(2);
+ await this.manager.$_setGrantDelay(ANOTHER_ROLE, this.grantDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+
+ // Grant role
+ this.executionDelay = time.duration.days(3);
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+
+ this.txResponse = await this.manager
+ .connect(this.admin)
+ .grantRole(ANOTHER_ROLE, this.user, this.executionDelay);
+ this.delay = this.grantDelay; // For testAsDelay
+ });
+
+ testAsDelay('grant', {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('does not grant role to the user yet', async function () {
+ const timestamp = await time.clockFromReceipt.timestamp(this.txResponse);
+ await expect(this.txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, this.executionDelay, timestamp + this.grantDelay, true);
+
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(timestamp + this.grantDelay); // inEffectSince
+ expect(access[1]).to.equal(this.executionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Not in effect yet
+ const currentTimestamp = await time.clock.timestamp();
+ expect(currentTimestamp).to.be.lt(access[0]);
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ this.executionDelay.toString(),
+ ]);
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('grants role to the user', async function () {
+ const timestamp = await time.clockFromReceipt.timestamp(this.txResponse);
+ await expect(this.txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, this.executionDelay, timestamp + this.grantDelay, true);
+
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(timestamp + this.grantDelay); // inEffectSince
+ expect(access[1]).to.equal(this.executionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ const currentTimestamp = await time.clock.timestamp();
+ expect(currentTimestamp).to.equal(access[0]);
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.executionDelay.toString(),
+ ]);
+ });
+ },
+ });
+ });
+
+ describe('without grant delay', function () {
+ beforeEach('set granting delay', async function () {
+ // Delay granting
+ this.grantDelay = 0;
+ await this.manager.$_setGrantDelay(ANOTHER_ROLE, this.grantDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ });
+
+ it('immediately grants the role to the user', async function () {
+ const executionDelay = time.duration.days(6);
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+ const txResponse = await this.manager
+ .connect(this.admin)
+ .grantRole(ANOTHER_ROLE, this.user, executionDelay);
+ const grantedAt = await time.clockFromReceipt.timestamp(txResponse);
+ await expect(txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, executionDelay, grantedAt, true);
+
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(grantedAt); // inEffectSince
+ expect(access[1]).to.equal(executionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ const currentTimestamp = await time.clock.timestamp();
+ expect(currentTimestamp).to.equal(access[0]);
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ executionDelay.toString(),
+ ]);
+ });
+ });
+ });
+
+ describe('when the user is already a role member', function () {
+ beforeEach('make user role member', async function () {
+ this.previousExecutionDelay = time.duration.days(6);
+ await this.manager.$_grantRole(ANOTHER_ROLE, this.user, 0, this.previousExecutionDelay);
+ this.oldAccess = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ });
+
+ describe('with grant delay', function () {
+ beforeEach('set granting delay', async function () {
+ // Delay granting
+ const grantDelay = time.duration.weeks(2);
+ await this.manager.$_setGrantDelay(ANOTHER_ROLE, grantDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ });
+
+ describe('when increasing the execution delay', function () {
+ beforeEach('set increased new execution delay', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+
+ this.newExecutionDelay = this.previousExecutionDelay + time.duration.days(4);
+ });
+
+ it('emits event and immediately changes the execution delay', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+ const txResponse = await this.manager
+ .connect(this.admin)
+ .grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
+ const timestamp = await time.clockFromReceipt.timestamp(txResponse);
+
+ await expect(txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, timestamp, false);
+
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
+ expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.newExecutionDelay.toString(),
+ ]);
+ });
+ });
+
+ describe('when decreasing the execution delay', function () {
+ beforeEach('decrease execution delay', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+
+ this.newExecutionDelay = this.previousExecutionDelay - time.duration.days(4);
+ this.txResponse = await this.manager
+ .connect(this.admin)
+ .grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
+ this.grantTimestamp = await time.clockFromReceipt.timestamp(this.txResponse);
+
+ this.delay = this.previousExecutionDelay - this.newExecutionDelay; // For testAsDelay
+ });
+
+ it('emits event', async function () {
+ await expect(this.txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, this.grantTimestamp + this.delay, false);
+ });
+
+ testAsDelay('execution delay effect', {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('does not change the execution delay yet', async function () {
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
+ expect(access[1]).to.equal(this.previousExecutionDelay); // currentDelay
+ expect(access[2]).to.equal(this.newExecutionDelay); // pendingDelay
+ expect(access[3]).to.equal(this.grantTimestamp + this.delay); // pendingDelayEffect
+
+ // Not in effect yet
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('changes the execution delay', async function () {
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+
+ expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
+ expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.newExecutionDelay.toString(),
+ ]);
+ });
+ },
+ });
+ });
+ });
+
+ describe('without grant delay', function () {
+ beforeEach('set granting delay', async function () {
+ // Delay granting
+ const grantDelay = 0;
+ await this.manager.$_setGrantDelay(ANOTHER_ROLE, grantDelay);
+ await time.increaseBy.timestamp(MINSETBACK);
+ });
+
+ describe('when increasing the execution delay', function () {
+ beforeEach('set increased new execution delay', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+
+ this.newExecutionDelay = this.previousExecutionDelay + time.duration.days(4);
+ });
+
+ it('emits event and immediately changes the execution delay', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+ const txResponse = await this.manager
+ .connect(this.admin)
+ .grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
+ const timestamp = await time.clockFromReceipt.timestamp(txResponse);
+
+ await expect(txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, timestamp, false);
+
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
+ expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.newExecutionDelay.toString(),
+ ]);
+ });
+ });
+
+ describe('when decreasing the execution delay', function () {
+ beforeEach('decrease execution delay', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+
+ this.newExecutionDelay = this.previousExecutionDelay - time.duration.days(4);
+ this.txResponse = await this.manager
+ .connect(this.admin)
+ .grantRole(ANOTHER_ROLE, this.user, this.newExecutionDelay);
+ this.grantTimestamp = await time.clockFromReceipt.timestamp(this.txResponse);
+
+ this.delay = this.previousExecutionDelay - this.newExecutionDelay; // For testAsDelay
+ });
+
+ it('emits event', async function () {
+ await expect(this.txResponse)
+ .to.emit(this.manager, 'RoleGranted')
+ .withArgs(ANOTHER_ROLE, this.user, this.newExecutionDelay, this.grantTimestamp + this.delay, false);
+ });
+
+ testAsDelay('execution delay effect', {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('does not change the execution delay yet', async function () {
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
+ expect(access[1]).to.equal(this.previousExecutionDelay); // currentDelay
+ expect(access[2]).to.equal(this.newExecutionDelay); // pendingDelay
+ expect(access[3]).to.equal(this.grantTimestamp + this.delay); // pendingDelayEffect
+
+ // Not in effect yet
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.previousExecutionDelay.toString(),
+ ]);
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('changes the execution delay', async function () {
+ // Access is correctly stored
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+
+ expect(access[0]).to.equal(this.oldAccess[0]); // inEffectSince
+ expect(access[1]).to.equal(this.newExecutionDelay); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // pendingDelayEffect
+
+ // Already in effect
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ this.newExecutionDelay.toString(),
+ ]);
+ });
+ },
+ });
+ });
+ });
+ });
+ });
+
+ describe('#revokeRole', function () {
+ describe('restrictions', function () {
+ beforeEach('set method and args', async function () {
+ const args = [ANOTHER_ROLE, this.other.address];
+ const method = this.manager.interface.getFunction('revokeRole(uint64,address)');
+ this.calldata = this.manager.interface.encodeFunctionData(method, args);
+
+ // Need to be set before revoking
+ await this.manager.$_grantRole(...args, 0, 0);
+ });
+
+ shouldBehaveLikeRoleAdminOperation(ANOTHER_ADMIN);
+ });
+
+ describe('when role has been granted', function () {
+ beforeEach('grant role with grant delay', async function () {
+ this.grantDelay = time.duration.weeks(1);
+ await this.manager.$_grantRole(ANOTHER_ROLE, this.user, this.grantDelay, 0);
+
+ this.delay = this.grantDelay; // For testAsDelay
+ });
+
+ testAsDelay('grant', {
+ before: function self() {
+ self.mineDelay = true;
+
+ it('revokes a granted role that will take effect in the future', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+
+ await expect(this.manager.connect(this.admin).revokeRole(ANOTHER_ROLE, this.user))
+ .to.emit(this.manager, 'RoleRevoked')
+ .withArgs(ANOTHER_ROLE, this.user);
+
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(0n); // inRoleSince
+ expect(access[1]).to.equal(0n); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // effect
+ });
+ },
+ after: function self() {
+ self.mineDelay = true;
+
+ it('revokes a granted role that already took effect', async function () {
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ true,
+ '0',
+ ]);
+
+ await expect(this.manager.connect(this.admin).revokeRole(ANOTHER_ROLE, this.user))
+ .to.emit(this.manager, 'RoleRevoked')
+ .withArgs(ANOTHER_ROLE, this.user);
+
+ expect(await this.manager.hasRole(ANOTHER_ROLE, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+
+ const access = await this.manager.getAccess(ANOTHER_ROLE, this.user);
+ expect(access[0]).to.equal(0n); // inRoleSince
+ expect(access[1]).to.equal(0n); // currentDelay
+ expect(access[2]).to.equal(0n); // pendingDelay
+ expect(access[3]).to.equal(0n); // effect
+ });
+ },
+ });
+ });
+
+ describe('when role has not been granted', function () {
+ it('has no effect', async function () {
+ expect(await this.manager.hasRole(this.roles.SOME.id, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+ await expect(this.manager.connect(this.roleAdmin).revokeRole(this.roles.SOME.id, this.user)).to.not.emit(
+ this.manager,
+ 'RoleRevoked',
+ );
+ expect(await this.manager.hasRole(this.roles.SOME.id, this.user).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+ });
+ });
+
+ it('reverts revoking PUBLIC_ROLE', async function () {
+ await expect(this.manager.connect(this.admin).revokeRole(this.roles.PUBLIC.id, this.user))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+ });
+ });
+
+ describe('self role operations', function () {
+ describe('#renounceRole', function () {
+ beforeEach('grant role', async function () {
+ this.role = { id: 783164n };
+ this.caller = this.user;
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 0);
+ });
+
+ it('renounces a role', async function () {
+ expect(await this.manager.hasRole(this.role.id, this.caller).then(formatAccess)).to.be.deep.equal([
+ true,
+ '0',
+ ]);
+ await expect(this.manager.connect(this.caller).renounceRole(this.role.id, this.caller))
+ .to.emit(this.manager, 'RoleRevoked')
+ .withArgs(this.role.id, this.caller);
+ expect(await this.manager.hasRole(this.role.id, this.caller).then(formatAccess)).to.be.deep.equal([
+ false,
+ '0',
+ ]);
+ });
+
+ it('reverts if renouncing the PUBLIC_ROLE', async function () {
+ await expect(this.manager.connect(this.caller).renounceRole(this.roles.PUBLIC.id, this.caller))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerLockedRole')
+ .withArgs(this.roles.PUBLIC.id);
+ });
+
+ it('reverts if renouncing with bad caller confirmation', async function () {
+ await expect(
+ this.manager.connect(this.caller).renounceRole(this.role.id, this.other),
+ ).to.be.revertedWithCustomError(this.manager, 'AccessManagerBadConfirmation');
+ });
+ });
+ });
+ });
+ });
+
+ describe('access managed self operations', function () {
+ describe('when calling a restricted target function', function () {
+ const method = 'fnRestricted()';
+
+ beforeEach('set required role', async function () {
+ this.role = { id: 785913n };
+ await this.manager.$_setTargetFunctionRole(
+ this.manager,
+ this.manager[method].getFragment().selector,
+ this.role.id,
+ );
+ });
+
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ this.caller = this.user;
+ this.calldata = this.manager.interface.encodeFunctionData(method, []);
+ });
+
+ shouldBehaveLikeASelfRestrictedOperation();
+ });
+
+ it('succeeds called by a role member', async function () {
+ await this.manager.$_grantRole(this.role.id, this.user, 0, 0);
+
+ await expect(this.manager.connect(this.user)[method]())
+ .to.emit(this.manager, 'CalledRestricted')
+ .withArgs(this.user);
+ });
+ });
+
+ describe('when calling a non-restricted target function', function () {
+ const method = 'fnUnrestricted()';
+
+ beforeEach('set required role', async function () {
+ this.role = { id: 879435n };
+ await this.manager.$_setTargetFunctionRole(
+ this.manager,
+ this.manager[method].getFragment().selector,
+ this.role.id,
+ );
+ });
+
+ it('succeeds called by anyone', async function () {
+ await expect(this.manager.connect(this.user)[method]())
+ .to.emit(this.manager, 'CalledUnrestricted')
+ .withArgs(this.user);
+ });
+ });
+ });
+
+ describe('access managed target operations', function () {
+ describe('when calling a restricted target function', function () {
+ const method = 'fnRestricted()';
+
+ beforeEach('set required role', async function () {
+ this.role = { id: 3597243n };
+ await this.manager.$_setTargetFunctionRole(
+ this.target,
+ this.target[method].getFragment().selector,
+ this.role.id,
+ );
+ });
+
+ describe('restrictions', function () {
+ beforeEach('set method and args', function () {
+ this.caller = this.user;
+ this.calldata = this.target.interface.encodeFunctionData(method, []);
+ });
+
+ shouldBehaveLikeAManagedRestrictedOperation();
+ });
+
+ it('succeeds called by a role member', async function () {
+ await this.manager.$_grantRole(this.role.id, this.user, 0, 0);
+
+ await expect(this.target.connect(this.user)[method]())
+ .to.emit(this.target, 'CalledRestricted')
+ .withArgs(this.user);
+ });
+ });
+
+ describe('when calling a non-restricted target function', function () {
+ const method = 'fnUnrestricted()';
+
+ beforeEach('set required role', async function () {
+ this.role = { id: 879435n };
+ await this.manager.$_setTargetFunctionRole(
+ this.target,
+ this.target[method].getFragment().selector,
+ this.role.id,
+ );
+ });
+
+ it('succeeds called by anyone', async function () {
+ await expect(this.target.connect(this.user)[method]())
+ .to.emit(this.target, 'CalledUnrestricted')
+ .withArgs(this.user);
+ });
+ });
+ });
+
+ describe('#schedule', function () {
+ beforeEach('set target function role', async function () {
+ this.method = this.target.fnRestricted.getFragment();
+ this.role = { id: 498305n };
+ this.caller = this.user;
+
+ await this.manager.$_setTargetFunctionRole(this.target, this.method.selector, this.role.id);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
+
+ this.calldata = this.target.interface.encodeFunctionData(this.method, []);
+ this.delay = time.duration.weeks(2);
+ });
+
+ describe('restrictions', function () {
+ testAsCanCall({
+ closed() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ const { schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+ await expect(schedule())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ open: {
+ callerIsTheManager: {
+ executing() {
+ it.skip('is not reachable because schedule is not restrictable');
+ },
+ notExecuting() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ const { schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+ await expect(schedule())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ },
+ callerIsNotTheManager: {
+ publicRoleIsRequired() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ // prepareOperation is not used here because it alters the next block timestamp
+ await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ specificRoleIsRequired: {
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ callerHasAnExecutionDelay: {
+ beforeGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ // prepareOperation is not used here because it alters the next block timestamp
+ await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ afterGrantDelay() {
+ it('succeeds', async function () {
+ // prepareOperation is not used here because it alters the next block timestamp
+ await this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48);
+ });
+ },
+ },
+ callerHasNoExecutionDelay: {
+ beforeGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ // prepareOperation is not used here because it alters the next block timestamp
+ await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ afterGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ // prepareOperation is not used here because it alters the next block timestamp
+ await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ },
+ },
+ roleGrantingIsNotDelayed: {
+ callerHasAnExecutionDelay() {
+ it('succeeds', async function () {
+ const { schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+
+ await schedule();
+ });
+ },
+ callerHasNoExecutionDelay() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ // prepareOperation is not used here because it alters the next block timestamp
+ await expect(this.manager.connect(this.caller).schedule(this.target, this.calldata, MAX_UINT48))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ },
+ },
+ requiredRoleIsNotGranted() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ const { schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+ await expect(schedule())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ },
+ },
+ },
+ });
+ });
+
+ it('schedules an operation at the specified execution date if it is larger than caller execution delay', async function () {
+ const { operationId, scheduledAt, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+
+ const txResponse = await schedule();
+
+ expect(await this.manager.getSchedule(operationId)).to.equal(scheduledAt + this.delay);
+ await expect(txResponse)
+ .to.emit(this.manager, 'OperationScheduled')
+ .withArgs(operationId, '1', scheduledAt + this.delay, this.caller, this.target, this.calldata);
+ });
+
+ it('schedules an operation at the minimum execution date if no specified execution date (when == 0)', async function () {
+ const executionDelay = await time.duration.hours(72);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, executionDelay);
+
+ const txResponse = await this.manager.connect(this.caller).schedule(this.target, this.calldata, 0);
+ const scheduledAt = await time.clockFromReceipt.timestamp(txResponse);
+
+ const operationId = await this.manager.hashOperation(this.caller, this.target, this.calldata);
+
+ expect(await this.manager.getSchedule(operationId)).to.equal(scheduledAt + executionDelay);
+ await expect(txResponse)
+ .to.emit(this.manager, 'OperationScheduled')
+ .withArgs(operationId, '1', scheduledAt + executionDelay, this.caller, this.target, this.calldata);
+ });
+
+ it('increases the nonce of an operation scheduled more than once', async function () {
+ // Setup and check initial nonce
+ const expectedOperationId = hashOperation(this.caller, this.target, this.calldata);
+ expect(await this.manager.getNonce(expectedOperationId)).to.equal('0');
+
+ // Schedule
+ const op1 = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+ await expect(op1.schedule())
+ .to.emit(this.manager, 'OperationScheduled')
+ .withArgs(op1.operationId, 1n, op1.scheduledAt + this.delay, this.caller, this.target, this.calldata);
+ expect(expectedOperationId).to.equal(op1.operationId);
+
+ // Consume
+ await time.increaseBy.timestamp(this.delay);
+ await this.manager.$_consumeScheduledOp(expectedOperationId);
+
+ // Check nonce
+ expect(await this.manager.getNonce(expectedOperationId)).to.equal('1');
+
+ // Schedule again
+ const op2 = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+ await expect(op2.schedule())
+ .to.emit(this.manager, 'OperationScheduled')
+ .withArgs(op2.operationId, 2n, op2.scheduledAt + this.delay, this.caller, this.target, this.calldata);
+ expect(expectedOperationId).to.equal(op2.operationId);
+
+ // Check final nonce
+ expect(await this.manager.getNonce(expectedOperationId)).to.equal('2');
+ });
+
+ it('reverts if the specified execution date is before the current timestamp + caller execution delay', async function () {
+ const executionDelay = time.duration.weeks(1) + this.delay;
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, executionDelay);
+
+ const { schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+
+ await expect(schedule())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+
+ it('reverts if an operation is already schedule', async function () {
+ const op1 = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+
+ await op1.schedule();
+
+ const op2 = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.delay,
+ });
+
+ await expect(op2.schedule())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerAlreadyScheduled')
+ .withArgs(op1.operationId);
+ });
+
+ it('panics scheduling calldata with less than 4 bytes', async function () {
+ const calldata = '0x1234'; // 2 bytes
+
+ // Managed contract
+ const op1 = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: calldata,
+ delay: this.delay,
+ });
+ await expect(op1.schedule()).to.be.revertedWithoutReason();
+
+ // Manager contract
+ const op2 = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.manager,
+ calldata: calldata,
+ delay: this.delay,
+ });
+ await expect(op2.schedule()).to.be.revertedWithoutReason();
+ });
+
+ it('reverts scheduling an unknown operation to the manager', async function () {
+ const calldata = '0x12345678';
+
+ const { schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.manager,
+ calldata,
+ delay: this.delay,
+ });
+
+ await expect(schedule())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.manager, calldata);
+ });
+ });
+
+ describe('#execute', function () {
+ beforeEach('set target function role', async function () {
+ this.method = this.target.fnRestricted.getFragment();
+ this.role = { id: 9825430n };
+ this.caller = this.user;
+
+ await this.manager.$_setTargetFunctionRole(this.target, this.method.selector, this.role.id);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 0);
+
+ this.calldata = this.target.interface.encodeFunctionData(this.method, []);
+ });
+
+ describe('restrictions', function () {
+ testAsCanCall({
+ closed() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ open: {
+ callerIsTheManager: {
+ executing() {
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ notExecuting() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ },
+ callerIsNotTheManager: {
+ publicRoleIsRequired() {
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ specificRoleIsRequired: {
+ requiredRoleIsGranted: {
+ roleGrantingIsDelayed: {
+ callerHasAnExecutionDelay: {
+ beforeGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ beforeEach('define schedule delay', function () {
+ this.scheduleIn = time.duration.days(21); // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ },
+ },
+ callerHasNoExecutionDelay: {
+ beforeGrantDelay() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ afterGrantDelay: function self() {
+ self.mineDelay = true;
+
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ },
+ },
+ roleGrantingIsNotDelayed: {
+ callerHasAnExecutionDelay() {
+ beforeEach('define schedule delay', function () {
+ this.scheduleIn = time.duration.days(15); // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation(LIKE_COMMON_SCHEDULABLE);
+ },
+ callerHasNoExecutionDelay() {
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ });
+ },
+ },
+ },
+ requiredRoleIsNotGranted() {
+ it('reverts as AccessManagerUnauthorizedCall', async function () {
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.caller, this.target, this.calldata.substring(0, 10));
+ });
+ },
+ },
+ },
+ },
+ });
+ });
+
+ it('executes with a delay consuming the scheduled operation', async function () {
+ const delay = time.duration.hours(4);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // Execution delay is needed so the operation is consumed
+
+ const { operationId, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay,
+ });
+ await schedule();
+ await time.increaseBy.timestamp(delay);
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.emit(this.manager, 'OperationExecuted')
+ .withArgs(operationId, 1n);
+
+ expect(await this.manager.getSchedule(operationId)).to.equal(0n);
+ });
+
+ it('executes with no delay consuming a scheduled operation', async function () {
+ const delay = time.duration.hours(4);
+
+ // give caller an execution delay
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1);
+
+ const { operationId, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay,
+ });
+ await schedule();
+
+ // remove the execution delay
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 0);
+
+ await time.increaseBy.timestamp(delay);
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.emit(this.manager, 'OperationExecuted')
+ .withArgs(operationId, 1n);
+
+ expect(await this.manager.getSchedule(operationId)).to.equal(0n);
+ });
+
+ it('keeps the original _executionId after finishing the call', async function () {
+ const executionIdBefore = await ethers.provider.getStorage(this.manager, EXECUTION_ID_STORAGE_SLOT);
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ const executionIdAfter = await ethers.provider.getStorage(this.manager, EXECUTION_ID_STORAGE_SLOT);
+ expect(executionIdBefore).to.equal(executionIdAfter);
+ });
+
+ it('reverts executing twice', async function () {
+ const delay = time.duration.hours(2);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // Execution delay is needed so the operation is consumed
+
+ const { operationId, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay,
+ });
+ await schedule();
+ await time.increaseBy.timestamp(delay);
+ await this.manager.connect(this.caller).execute(this.target, this.calldata);
+ await expect(this.manager.connect(this.caller).execute(this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
+ .withArgs(operationId);
+ });
+ });
+
+ describe('#consumeScheduledOp', function () {
+ beforeEach('define scheduling parameters', async function () {
+ const method = this.target.fnRestricted.getFragment();
+ this.caller = await ethers.getSigner(this.target.target);
+ await impersonate(this.caller.address);
+ this.calldata = this.target.interface.encodeFunctionData(method, []);
+ this.role = { id: 9834983n };
+
+ await this.manager.$_setTargetFunctionRole(this.target, method.selector, this.role.id);
+ await this.manager.$_grantRole(this.role.id, this.caller, 0, 1); // nonzero execution delay
+
+ this.scheduleIn = time.duration.hours(10); // For testAsSchedulableOperation
+ });
+
+ describe('when caller is not consuming scheduled operation', function () {
+ beforeEach('set consuming false', async function () {
+ await this.target.setIsConsumingScheduledOp(false, ethers.toBeHex(CONSUMING_SCHEDULE_STORAGE_SLOT, 32));
+ });
+
+ it('reverts as AccessManagerUnauthorizedConsume', async function () {
+ await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedConsume')
+ .withArgs(this.caller);
+ });
+ });
+
+ describe('when caller is consuming scheduled operation', function () {
+ beforeEach('set consuming true', async function () {
+ await this.target.setIsConsumingScheduledOp(true, ethers.toBeHex(CONSUMING_SCHEDULE_STORAGE_SLOT, 32));
+ });
+
+ testAsSchedulableOperation({
+ scheduled: {
+ before() {
+ it('reverts as AccessManagerNotReady', async function () {
+ await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotReady')
+ .withArgs(this.operationId);
+ });
+ },
+ after() {
+ it('consumes the scheduled operation and resets timepoint', async function () {
+ expect(await this.manager.getSchedule(this.operationId)).to.equal(this.scheduledAt + this.scheduleIn);
+
+ await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
+ .to.emit(this.manager, 'OperationExecuted')
+ .withArgs(this.operationId, 1n);
+ expect(await this.manager.getSchedule(this.operationId)).to.equal(0n);
+ });
+ },
+ expired() {
+ it('reverts as AccessManagerExpired', async function () {
+ await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerExpired')
+ .withArgs(this.operationId);
+ });
+ },
+ },
+ notScheduled() {
+ it('reverts as AccessManagerNotScheduled', async function () {
+ await expect(this.manager.connect(this.caller).consumeScheduledOp(this.caller, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
+ .withArgs(this.operationId);
+ });
+ },
+ });
+ });
+ });
+
+ describe('#cancelScheduledOp', function () {
+ beforeEach('setup scheduling', async function () {
+ this.method = this.target.fnRestricted.getFragment();
+ this.caller = this.roles.SOME.members[0];
+ await this.manager.$_setTargetFunctionRole(this.target, this.method.selector, this.roles.SOME.id);
+ await this.manager.$_grantRole(this.roles.SOME.id, this.caller, 0, 1); // nonzero execution delay
+
+ this.calldata = this.target.interface.encodeFunctionData(this.method, []);
+ this.scheduleIn = time.duration.days(10); // For testAsSchedulableOperation
+ });
+
+ testAsSchedulableOperation({
+ scheduled: {
+ before() {
+ describe('when caller is the scheduler', function () {
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata);
+ });
+ });
+
+ describe('when caller is an admin', function () {
+ it('succeeds', async function () {
+ await this.manager.connect(this.roles.ADMIN.members[0]).cancel(this.caller, this.target, this.calldata);
+ });
+ });
+
+ describe('when caller is the role guardian', function () {
+ it('succeeds', async function () {
+ await this.manager
+ .connect(this.roles.SOME_GUARDIAN.members[0])
+ .cancel(this.caller, this.target, this.calldata);
+ });
+ });
+
+ describe('when caller is any other account', function () {
+ it('reverts as AccessManagerUnauthorizedCancel', async function () {
+ await expect(this.manager.connect(this.other).cancel(this.caller, this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCancel')
+ .withArgs(this.other, this.caller, this.target, this.method.selector);
+ });
+ });
+ },
+ after() {
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata);
+ });
+ },
+ expired() {
+ it('succeeds', async function () {
+ await this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata);
+ });
+ },
+ },
+ notScheduled() {
+ it('reverts as AccessManagerNotScheduled', async function () {
+ await expect(this.manager.cancel(this.caller, this.target, this.calldata))
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
+ .withArgs(this.operationId);
+ });
+ },
+ });
+
+ it('cancels an operation and resets schedule', async function () {
+ const { operationId, schedule } = await prepareOperation(this.manager, {
+ caller: this.caller,
+ target: this.target,
+ calldata: this.calldata,
+ delay: this.scheduleIn,
+ });
+ await schedule();
+ await expect(this.manager.connect(this.caller).cancel(this.caller, this.target, this.calldata))
+ .to.emit(this.manager, 'OperationCanceled')
+ .withArgs(operationId, 1n);
+ expect(await this.manager.getSchedule(operationId)).to.equal('0');
+ });
+ });
+
+ describe('with Ownable target contract', function () {
+ const roleId = 1n;
+
+ beforeEach(async function () {
+ this.ownable = await ethers.deployContract('$Ownable', [this.manager]);
+
+ // add user to role
+ await this.manager.$_grantRole(roleId, this.user, 0, 0);
+ });
+
+ it('initial state', async function () {
+ expect(await this.ownable.owner()).to.equal(this.manager);
+ });
+
+ describe('Contract is closed', function () {
+ beforeEach(async function () {
+ await this.manager.$_setTargetClosed(this.ownable, true);
+ });
+
+ it('directly call: reverts', async function () {
+ await expect(this.ownable.connect(this.user).$_checkOwner())
+ .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
+ .withArgs(this.user);
+ });
+
+ it('relayed call (with role): reverts', async function () {
+ await expect(
+ this.manager.connect(this.user).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector),
+ )
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.user, this.ownable, this.ownable.$_checkOwner.getFragment().selector);
+ });
+
+ it('relayed call (without role): reverts', async function () {
+ await expect(
+ this.manager.connect(this.other).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector),
+ )
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.other, this.ownable, this.ownable.$_checkOwner.getFragment().selector);
+ });
+ });
+
+ describe('Contract is managed', function () {
+ describe('function is open to specific role', function () {
+ beforeEach(async function () {
+ await this.manager.$_setTargetFunctionRole(
+ this.ownable,
+ this.ownable.$_checkOwner.getFragment().selector,
+ roleId,
+ );
+ });
+
+ it('directly call: reverts', async function () {
+ await expect(this.ownable.connect(this.user).$_checkOwner())
+ .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
+ .withArgs(this.user);
+ });
+
+ it('relayed call (with role): success', async function () {
+ await this.manager.connect(this.user).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector);
+ });
+
+ it('relayed call (without role): reverts', async function () {
+ await expect(
+ this.manager.connect(this.other).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector),
+ )
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerUnauthorizedCall')
+ .withArgs(this.other, this.ownable, this.ownable.$_checkOwner.getFragment().selector);
+ });
+ });
+
+ describe('function is open to public role', function () {
+ beforeEach(async function () {
+ await this.manager.$_setTargetFunctionRole(
+ this.ownable,
+ this.ownable.$_checkOwner.getFragment().selector,
+ this.roles.PUBLIC.id,
+ );
+ });
+
+ it('directly call: reverts', async function () {
+ await expect(this.ownable.connect(this.user).$_checkOwner())
+ .to.be.revertedWithCustomError(this.ownable, 'OwnableUnauthorizedAccount')
+ .withArgs(this.user);
+ });
+
+ it('relayed call (with role): success', async function () {
+ await this.manager.connect(this.user).execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector);
+ });
+
+ it('relayed call (without role): success', async function () {
+ await this.manager
+ .connect(this.other)
+ .execute(this.ownable, this.ownable.$_checkOwner.getFragment().selector);
+ });
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AuthorityUtils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AuthorityUtils.test.js
new file mode 100644
index 000000000..905913f14
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/access/manager/AuthorityUtils.test.js
@@ -0,0 +1,102 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [user, other] = await ethers.getSigners();
+
+ const mock = await ethers.deployContract('$AuthorityUtils');
+ const notAuthorityMock = await ethers.deployContract('NotAuthorityMock');
+ const authorityNoDelayMock = await ethers.deployContract('AuthorityNoDelayMock');
+ const authorityDelayMock = await ethers.deployContract('AuthorityDelayMock');
+ const authorityNoResponse = await ethers.deployContract('AuthorityNoResponse');
+
+ return {
+ user,
+ other,
+ mock,
+ notAuthorityMock,
+ authorityNoDelayMock,
+ authorityDelayMock,
+ authorityNoResponse,
+ };
+}
+
+describe('AuthorityUtils', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('canCallWithDelay', function () {
+ describe('when authority does not have a canCall function', function () {
+ beforeEach(async function () {
+ this.authority = this.notAuthorityMock;
+ });
+
+ it('returns (immediate = 0, delay = 0)', async function () {
+ const { immediate, delay } = await this.mock.$canCallWithDelay(
+ this.authority,
+ this.user,
+ this.other,
+ '0x12345678',
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ });
+
+ describe('when authority has no delay', function () {
+ beforeEach(async function () {
+ this.authority = this.authorityNoDelayMock;
+ this.immediate = true;
+ await this.authority._setImmediate(this.immediate);
+ });
+
+ it('returns (immediate, delay = 0)', async function () {
+ const { immediate, delay } = await this.mock.$canCallWithDelay(
+ this.authority,
+ this.user,
+ this.other,
+ '0x12345678',
+ );
+ expect(immediate).to.equal(this.immediate);
+ expect(delay).to.equal(0n);
+ });
+ });
+
+ describe('when authority replies with a delay', function () {
+ beforeEach(async function () {
+ this.authority = this.authorityDelayMock;
+ });
+
+ for (const immediate of [true, false]) {
+ for (const delay of [0n, 42n]) {
+ it(`returns (immediate=${immediate}, delay=${delay})`, async function () {
+ await this.authority._setImmediate(immediate);
+ await this.authority._setDelay(delay);
+ const result = await this.mock.$canCallWithDelay(this.authority, this.user, this.other, '0x12345678');
+ expect(result.immediate).to.equal(immediate);
+ expect(result.delay).to.equal(delay);
+ });
+ }
+ }
+ });
+
+ describe('when authority replies with empty data', function () {
+ beforeEach(async function () {
+ this.authority = this.authorityNoResponse;
+ });
+
+ it('returns (immediate = 0, delay = 0)', async function () {
+ const { immediate, delay } = await this.mock.$canCallWithDelay(
+ this.authority,
+ this.user,
+ this.other,
+ '0x12345678',
+ );
+ expect(immediate).to.be.false;
+ expect(delay).to.equal(0n);
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC4337Utils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC4337Utils.test.js
new file mode 100644
index 000000000..7c292910d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC4337Utils.test.js
@@ -0,0 +1,288 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { packValidationData, UserOperation } = require('../../helpers/erc4337');
+const { deployEntrypoint } = require('../../helpers/erc4337-entrypoint');
+const { MAX_UINT48 } = require('../../helpers/constants');
+const ADDRESS_ONE = '0x0000000000000000000000000000000000000001';
+
+const fixture = async () => {
+ const { entrypoint } = await deployEntrypoint();
+ const [authorizer, sender, factory, paymaster] = await ethers.getSigners();
+ const utils = await ethers.deployContract('$ERC4337Utils');
+ const SIG_VALIDATION_SUCCESS = await utils.$SIG_VALIDATION_SUCCESS();
+ const SIG_VALIDATION_FAILED = await utils.$SIG_VALIDATION_FAILED();
+ return { utils, authorizer, sender, entrypoint, factory, paymaster, SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILED };
+};
+
+describe('ERC4337Utils', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('parseValidationData', function () {
+ it('parses the validation data', async function () {
+ const authorizer = this.authorizer;
+ const validUntil = 0x12345678n;
+ const validAfter = 0x9abcdef0n;
+ const validationData = packValidationData(validAfter, validUntil, authorizer);
+
+ expect(this.utils.$parseValidationData(validationData)).to.eventually.deep.equal([
+ authorizer.address,
+ validAfter,
+ validUntil,
+ ]);
+ });
+
+ it('returns an type(uint48).max if until is 0', async function () {
+ const authorizer = this.authorizer;
+ const validAfter = 0x12345678n;
+ const validationData = packValidationData(validAfter, 0, authorizer);
+
+ expect(this.utils.$parseValidationData(validationData)).to.eventually.deep.equal([
+ authorizer.address,
+ validAfter,
+ MAX_UINT48,
+ ]);
+ });
+
+ it('parse canonical values', async function () {
+ expect(this.utils.$parseValidationData(this.SIG_VALIDATION_SUCCESS)).to.eventually.deep.equal([
+ ethers.ZeroAddress,
+ 0n,
+ MAX_UINT48,
+ ]);
+
+ expect(this.utils.$parseValidationData(this.SIG_VALIDATION_FAILED)).to.eventually.deep.equal([
+ ADDRESS_ONE,
+ 0n,
+ MAX_UINT48,
+ ]);
+ });
+ });
+
+ describe('packValidationData', function () {
+ it('packs the validation data', async function () {
+ const authorizer = this.authorizer;
+ const validUntil = 0x12345678n;
+ const validAfter = 0x9abcdef0n;
+ const validationData = packValidationData(validAfter, validUntil, authorizer);
+
+ expect(
+ this.utils.$packValidationData(ethers.Typed.address(authorizer), validAfter, validUntil),
+ ).to.eventually.equal(validationData);
+ });
+
+ it('packs the validation data (bool)', async function () {
+ const success = false;
+ const validUntil = 0x12345678n;
+ const validAfter = 0x9abcdef0n;
+ const validationData = packValidationData(validAfter, validUntil, false);
+
+ expect(this.utils.$packValidationData(ethers.Typed.bool(success), validAfter, validUntil)).to.eventually.equal(
+ validationData,
+ );
+ });
+
+ it('packing reproduced canonical values', async function () {
+ expect(this.utils.$packValidationData(ethers.Typed.address(ethers.ZeroAddress), 0n, 0n)).to.eventually.equal(
+ this.SIG_VALIDATION_SUCCESS,
+ );
+ expect(this.utils.$packValidationData(ethers.Typed.bool(true), 0n, 0n)).to.eventually.equal(
+ this.SIG_VALIDATION_SUCCESS,
+ );
+ expect(this.utils.$packValidationData(ethers.Typed.address(ADDRESS_ONE), 0n, 0n)).to.eventually.equal(
+ this.SIG_VALIDATION_FAILED,
+ );
+ expect(this.utils.$packValidationData(ethers.Typed.bool(false), 0n, 0n)).to.eventually.equal(
+ this.SIG_VALIDATION_FAILED,
+ );
+ });
+ });
+
+ describe('combineValidationData', function () {
+ const validUntil1 = 0x12345678n;
+ const validAfter1 = 0x9abcdef0n;
+ const validUntil2 = 0x87654321n;
+ const validAfter2 = 0xabcdef90n;
+
+ it('combines the validation data', async function () {
+ const validationData1 = packValidationData(validAfter1, validUntil1, ethers.ZeroAddress);
+ const validationData2 = packValidationData(validAfter2, validUntil2, ethers.ZeroAddress);
+ const expected = packValidationData(validAfter2, validUntil1, true);
+
+ // check symmetry
+ expect(this.utils.$combineValidationData(validationData1, validationData2)).to.eventually.equal(expected);
+ expect(this.utils.$combineValidationData(validationData2, validationData1)).to.eventually.equal(expected);
+ });
+
+ for (const [authorizer1, authorizer2] of [
+ [ethers.ZeroAddress, '0xbf023313b891fd6000544b79e353323aa94a4f29'],
+ ['0xbf023313b891fd6000544b79e353323aa94a4f29', ethers.ZeroAddress],
+ ]) {
+ it('returns SIG_VALIDATION_FAILURE if one of the authorizers is not address(0)', async function () {
+ const validationData1 = packValidationData(validAfter1, validUntil1, authorizer1);
+ const validationData2 = packValidationData(validAfter2, validUntil2, authorizer2);
+ const expected = packValidationData(validAfter2, validUntil1, false);
+
+ // check symmetry
+ expect(this.utils.$combineValidationData(validationData1, validationData2)).to.eventually.equal(expected);
+ expect(this.utils.$combineValidationData(validationData2, validationData1)).to.eventually.equal(expected);
+ });
+ }
+ });
+
+ describe('getValidationData', function () {
+ it('returns the validation data with valid validity range', async function () {
+ const aggregator = this.authorizer;
+ const validAfter = 0;
+ const validUntil = MAX_UINT48;
+ const validationData = packValidationData(validAfter, validUntil, aggregator);
+
+ expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, false]);
+ });
+
+ it('returns the validation data with invalid validity range (expired)', async function () {
+ const aggregator = this.authorizer;
+ const validAfter = 0;
+ const validUntil = 1;
+ const validationData = packValidationData(validAfter, validUntil, aggregator);
+
+ expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, true]);
+ });
+
+ it('returns the validation data with invalid validity range (not yet valid)', async function () {
+ const aggregator = this.authorizer;
+ const validAfter = MAX_UINT48;
+ const validUntil = MAX_UINT48;
+ const validationData = packValidationData(validAfter, validUntil, aggregator);
+
+ expect(this.utils.$getValidationData(validationData)).to.eventually.deep.equal([aggregator.address, true]);
+ });
+
+ it('returns address(0) and false for validationData = 0', function () {
+ expect(this.utils.$getValidationData(0n)).to.eventually.deep.equal([ethers.ZeroAddress, false]);
+ });
+ });
+
+ describe('hash', function () {
+ it('returns the operation hash with specified entrypoint and chainId', async function () {
+ const userOp = new UserOperation({ sender: this.sender, nonce: 1 });
+ const chainId = await ethers.provider.getNetwork().then(({ chainId }) => chainId);
+ const otherChainId = 0xdeadbeef;
+
+ // check that helper matches entrypoint logic
+ expect(this.entrypoint.getUserOpHash(userOp.packed)).to.eventually.equal(userOp.hash(this.entrypoint, chainId));
+
+ // check library against helper
+ expect(this.utils.$hash(userOp.packed, this.entrypoint, chainId)).to.eventually.equal(
+ userOp.hash(this.entrypoint, chainId),
+ );
+ expect(this.utils.$hash(userOp.packed, this.entrypoint, otherChainId)).to.eventually.equal(
+ userOp.hash(this.entrypoint, otherChainId),
+ );
+ });
+ });
+
+ describe('userOp values', function () {
+ describe('intiCode', function () {
+ beforeEach(async function () {
+ this.userOp = new UserOperation({
+ sender: this.sender,
+ nonce: 1,
+ verificationGas: 0x12345678n,
+ factory: this.factory,
+ factoryData: '0x123456',
+ });
+
+ this.emptyUserOp = new UserOperation({
+ sender: this.sender,
+ nonce: 1,
+ });
+ });
+
+ it('returns factory', async function () {
+ expect(this.utils.$factory(this.userOp.packed)).to.eventually.equal(this.factory);
+ expect(this.utils.$factory(this.emptyUserOp.packed)).to.eventually.equal(ethers.ZeroAddress);
+ });
+
+ it('returns factoryData', async function () {
+ expect(this.utils.$factoryData(this.userOp.packed)).to.eventually.equal('0x123456');
+ expect(this.utils.$factoryData(this.emptyUserOp.packed)).to.eventually.equal('0x');
+ });
+ });
+
+ it('returns verificationGasLimit', async function () {
+ const userOp = new UserOperation({ sender: this.sender, nonce: 1, verificationGas: 0x12345678n });
+ expect(this.utils.$verificationGasLimit(userOp.packed)).to.eventually.equal(userOp.verificationGas);
+ });
+
+ it('returns callGasLimit', async function () {
+ const userOp = new UserOperation({ sender: this.sender, nonce: 1, callGas: 0x12345678n });
+ expect(this.utils.$callGasLimit(userOp.packed)).to.eventually.equal(userOp.callGas);
+ });
+
+ it('returns maxPriorityFeePerGas', async function () {
+ const userOp = new UserOperation({ sender: this.sender, nonce: 1, maxPriorityFee: 0x12345678n });
+ expect(this.utils.$maxPriorityFeePerGas(userOp.packed)).to.eventually.equal(userOp.maxPriorityFee);
+ });
+
+ it('returns maxFeePerGas', async function () {
+ const userOp = new UserOperation({ sender: this.sender, nonce: 1, maxFeePerGas: 0x12345678n });
+ expect(this.utils.$maxFeePerGas(userOp.packed)).to.eventually.equal(userOp.maxFeePerGas);
+ });
+
+ it('returns gasPrice', async function () {
+ const userOp = new UserOperation({
+ sender: this.sender,
+ nonce: 1,
+ maxPriorityFee: 0x12345678n,
+ maxFeePerGas: 0x87654321n,
+ });
+ expect(this.utils.$gasPrice(userOp.packed)).to.eventually.equal(userOp.maxPriorityFee);
+ });
+
+ describe('paymasterAndData', function () {
+ beforeEach(async function () {
+ this.userOp = new UserOperation({
+ sender: this.sender,
+ nonce: 1,
+ paymaster: this.paymaster,
+ paymasterVerificationGasLimit: 0x12345678n,
+ paymasterPostOpGasLimit: 0x87654321n,
+ paymasterData: '0xbeefcafe',
+ });
+
+ this.emptyUserOp = new UserOperation({
+ sender: this.sender,
+ nonce: 1,
+ });
+ });
+
+ it('returns paymaster', async function () {
+ expect(this.utils.$paymaster(this.userOp.packed)).to.eventually.equal(this.userOp.paymaster);
+ expect(this.utils.$paymaster(this.emptyUserOp.packed)).to.eventually.equal(ethers.ZeroAddress);
+ });
+
+ it('returns verificationGasLimit', async function () {
+ expect(this.utils.$paymasterVerificationGasLimit(this.userOp.packed)).to.eventually.equal(
+ this.userOp.paymasterVerificationGasLimit,
+ );
+ expect(this.utils.$paymasterVerificationGasLimit(this.emptyUserOp.packed)).to.eventually.equal(0n);
+ });
+
+ it('returns postOpGasLimit', async function () {
+ expect(this.utils.$paymasterPostOpGasLimit(this.userOp.packed)).to.eventually.equal(
+ this.userOp.paymasterPostOpGasLimit,
+ );
+ expect(this.utils.$paymasterPostOpGasLimit(this.emptyUserOp.packed)).to.eventually.equal(0n);
+ });
+
+ it('returns data', async function () {
+ expect(this.utils.$paymasterData(this.userOp.packed)).to.eventually.equal(this.userOp.paymasterData);
+ expect(this.utils.$paymasterData(this.emptyUserOp.packed)).to.eventually.equal('0x');
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.t.sol
new file mode 100644
index 000000000..fdd4edf59
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.t.sol
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.24;
+
+// Parts of this test file are adapted from Adam Egyed (@adamegyed) proof of concept available at:
+// https://github.com/adamegyed/erc7579-execute-vulnerability/tree/4589a30ff139e143d6c57183ac62b5c029217a90
+//
+// solhint-disable no-console
+
+import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
+import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
+import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
+import {PackedUserOperation, IAccount, IEntryPoint} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";
+import {ERC4337Utils} from "@openzeppelin/contracts/account/utils/draft-ERC4337Utils.sol";
+import {ERC7579Utils, Mode, CallType, ExecType, ModeSelector, ModePayload, Execution} from "@openzeppelin/contracts/account/utils/draft-ERC7579Utils.sol";
+import {Test, Vm, console} from "forge-std/Test.sol";
+
+contract SampleAccount is IAccount, Ownable {
+ using ECDSA for *;
+ using MessageHashUtils for *;
+ using ERC4337Utils for *;
+ using ERC7579Utils for *;
+
+ IEntryPoint internal constant ENTRY_POINT = IEntryPoint(payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032));
+
+ event Log(bool duringValidation, Execution[] calls);
+
+ error UnsupportedCallType(CallType callType);
+
+ constructor(address initialOwner) Ownable(initialOwner) {}
+
+ function validateUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingAccountFunds
+ ) external override returns (uint256 validationData) {
+ require(msg.sender == address(ENTRY_POINT), "only from EP");
+ // Check signature
+ if (userOpHash.toEthSignedMessageHash().recover(userOp.signature) != owner()) {
+ revert OwnableUnauthorizedAccount(_msgSender());
+ }
+
+ // If this is an execute call with a batch operation, log the call details from the calldata
+ if (bytes4(userOp.callData[0x00:0x04]) == this.execute.selector) {
+ (CallType callType, , , ) = Mode.wrap(bytes32(userOp.callData[0x04:0x24])).decodeMode();
+
+ if (callType == ERC7579Utils.CALLTYPE_BATCH) {
+ // Remove the selector
+ bytes calldata params = userOp.callData[0x04:];
+
+ // Use the same vulnerable assignment technique here, but assert afterwards that the checks aren't
+ // broken here by comparing to the result of `abi.decode(...)`.
+ bytes calldata executionCalldata;
+ assembly ("memory-safe") {
+ let dataptr := add(params.offset, calldataload(add(params.offset, 0x20)))
+ executionCalldata.offset := add(dataptr, 32)
+ executionCalldata.length := calldataload(dataptr)
+ }
+ // Check that this decoding step is done correctly.
+ (, bytes memory executionCalldataMemory) = abi.decode(params, (bytes32, bytes));
+
+ require(
+ keccak256(executionCalldata) == keccak256(executionCalldataMemory),
+ "decoding during validation failed"
+ );
+ // Now, we know that we have `bytes calldata executionCalldata` as would be decoded by the solidity
+ // builtin decoder for the `execute` function.
+
+ // This is where the vulnerability from ExecutionLib results in a different result between validation
+ // andexecution.
+
+ emit Log(true, executionCalldata.decodeBatch());
+ }
+ }
+
+ if (missingAccountFunds > 0) {
+ (bool success, ) = payable(msg.sender).call{value: missingAccountFunds}("");
+ success; // Silence warning. The entrypoint should validate the result.
+ }
+
+ return ERC4337Utils.SIG_VALIDATION_SUCCESS;
+ }
+
+ function execute(Mode mode, bytes calldata executionCalldata) external payable {
+ require(msg.sender == address(this) || msg.sender == address(ENTRY_POINT), "not auth");
+
+ (CallType callType, ExecType execType, , ) = mode.decodeMode();
+
+ // check if calltype is batch or single
+ if (callType == ERC7579Utils.CALLTYPE_SINGLE) {
+ executionCalldata.execSingle(execType);
+ } else if (callType == ERC7579Utils.CALLTYPE_BATCH) {
+ executionCalldata.execBatch(execType);
+
+ emit Log(false, executionCalldata.decodeBatch());
+ } else if (callType == ERC7579Utils.CALLTYPE_DELEGATECALL) {
+ executionCalldata.execDelegateCall(execType);
+ } else {
+ revert UnsupportedCallType(callType);
+ }
+ }
+}
+
+contract ERC7579UtilsTest is Test {
+ using MessageHashUtils for *;
+ using ERC4337Utils for *;
+ using ERC7579Utils for *;
+
+ IEntryPoint private constant ENTRYPOINT = IEntryPoint(payable(0x0000000071727De22E5E9d8BAf0edAc6f37da032));
+ address private _owner;
+ uint256 private _ownerKey;
+ address private _account;
+ address private _beneficiary;
+ address private _recipient1;
+ address private _recipient2;
+
+ constructor() {
+ vm.etch(0x0000000071727De22E5E9d8BAf0edAc6f37da032, vm.readFileBinary("test/bin/EntryPoint070.bytecode"));
+ vm.etch(0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C, vm.readFileBinary("test/bin/SenderCreator070.bytecode"));
+
+ // signing key
+ (_owner, _ownerKey) = makeAddrAndKey("owner");
+
+ // ERC-4337 account
+ _account = address(new SampleAccount(_owner));
+ vm.deal(_account, 1 ether);
+
+ // other
+ _beneficiary = makeAddr("beneficiary");
+ _recipient1 = makeAddr("recipient1");
+ _recipient2 = makeAddr("recipient2");
+ }
+
+ function testExecuteBatchDecodeCorrectly() public {
+ Execution[] memory calls = new Execution[](2);
+ calls[0] = Execution({target: _recipient1, value: 1 wei, callData: ""});
+ calls[1] = Execution({target: _recipient2, value: 1 wei, callData: ""});
+
+ PackedUserOperation[] memory userOps = new PackedUserOperation[](1);
+ userOps[0] = PackedUserOperation({
+ sender: _account,
+ nonce: 0,
+ initCode: "",
+ callData: abi.encodeCall(
+ SampleAccount.execute,
+ (
+ ERC7579Utils.encodeMode(
+ ERC7579Utils.CALLTYPE_BATCH,
+ ERC7579Utils.EXECTYPE_DEFAULT,
+ ModeSelector.wrap(0x00),
+ ModePayload.wrap(0x00)
+ ),
+ ERC7579Utils.encodeBatch(calls)
+ )
+ ),
+ accountGasLimits: _packGas(500_000, 500_000),
+ preVerificationGas: 0,
+ gasFees: _packGas(1, 1),
+ paymasterAndData: "",
+ signature: ""
+ });
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ _ownerKey,
+ this.hashUserOperation(userOps[0]).toEthSignedMessageHash()
+ );
+ userOps[0].signature = abi.encodePacked(r, s, v);
+
+ vm.recordLogs();
+ ENTRYPOINT.handleOps(userOps, payable(_beneficiary));
+
+ assertEq(_recipient1.balance, 1 wei);
+ assertEq(_recipient2.balance, 1 wei);
+
+ _collectAndPrintLogs(false);
+ }
+
+ function testExecuteBatchDecodeEmpty() public {
+ bytes memory fakeCalls = abi.encodePacked(
+ uint256(1), // Length of execution[]
+ uint256(0x20), // offset
+ uint256(uint160(_recipient1)), // target
+ uint256(1), // value: 1 wei
+ uint256(0x60), // offset of data
+ uint256(0) // length of
+ );
+
+ PackedUserOperation[] memory userOps = new PackedUserOperation[](1);
+ userOps[0] = PackedUserOperation({
+ sender: _account,
+ nonce: 0,
+ initCode: "",
+ callData: abi.encodeCall(
+ SampleAccount.execute,
+ (
+ ERC7579Utils.encodeMode(
+ ERC7579Utils.CALLTYPE_BATCH,
+ ERC7579Utils.EXECTYPE_DEFAULT,
+ ModeSelector.wrap(0x00),
+ ModePayload.wrap(0x00)
+ ),
+ abi.encodePacked(
+ uint256(0x70) // fake offset pointing to paymasterAndData
+ )
+ )
+ ),
+ accountGasLimits: _packGas(500_000, 500_000),
+ preVerificationGas: 0,
+ gasFees: _packGas(1, 1),
+ paymasterAndData: abi.encodePacked(address(0), fakeCalls),
+ signature: ""
+ });
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ _ownerKey,
+ this.hashUserOperation(userOps[0]).toEthSignedMessageHash()
+ );
+ userOps[0].signature = abi.encodePacked(r, s, v);
+
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IEntryPoint.FailedOpWithRevert.selector,
+ 0,
+ "AA23 reverted",
+ abi.encodeWithSelector(ERC7579Utils.ERC7579DecodingError.selector)
+ )
+ );
+ ENTRYPOINT.handleOps(userOps, payable(_beneficiary));
+
+ _collectAndPrintLogs(false);
+ }
+
+ function testExecuteBatchDecodeDifferent() public {
+ bytes memory execCallData = abi.encodePacked(
+ uint256(0x20), // offset pointing to the next segment
+ uint256(5), // Length of execution[]
+ uint256(0), // offset of calls[0], and target (!!)
+ uint256(0x20), // offset of calls[1], and value (!!)
+ uint256(0), // offset of calls[2], and rel offset of data (!!)
+ uint256(0) // offset of calls[3].
+ // There is one more to read by the array length, but it's not present here. This will be
+ // paymasterAndData.length during validation, pointing to an all-zero call.
+ // During execution, the offset will be 0, pointing to a call with value.
+ );
+
+ PackedUserOperation[] memory userOps = new PackedUserOperation[](1);
+ userOps[0] = PackedUserOperation({
+ sender: _account,
+ nonce: 0,
+ initCode: "",
+ callData: abi.encodePacked(
+ SampleAccount.execute.selector,
+ ERC7579Utils.encodeMode(
+ ERC7579Utils.CALLTYPE_BATCH,
+ ERC7579Utils.EXECTYPE_DEFAULT,
+ ModeSelector.wrap(0x00),
+ ModePayload.wrap(0x00)
+ ),
+ uint256(0x5c), // offset pointing to the next segment
+ uint224(type(uint224).max), // Padding to align the `bytes` types
+ // type(uint256).max, // unknown padding
+ uint256(execCallData.length), // Length of the data
+ execCallData
+ ),
+ accountGasLimits: _packGas(500_000, 500_000),
+ preVerificationGas: 0,
+ gasFees: _packGas(1, 1),
+ paymasterAndData: abi.encodePacked(uint256(0), uint256(0)), // padding length to create an offset
+ signature: ""
+ });
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(
+ _ownerKey,
+ this.hashUserOperation(userOps[0]).toEthSignedMessageHash()
+ );
+ userOps[0].signature = abi.encodePacked(r, s, v);
+
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IEntryPoint.FailedOpWithRevert.selector,
+ 0,
+ "AA23 reverted",
+ abi.encodeWithSelector(ERC7579Utils.ERC7579DecodingError.selector)
+ )
+ );
+ ENTRYPOINT.handleOps(userOps, payable(_beneficiary));
+
+ _collectAndPrintLogs(true);
+ }
+
+ function testDecodeBatch() public {
+ // BAD: buffer empty
+ vm.expectRevert(ERC7579Utils.ERC7579DecodingError.selector);
+ this.callDecodeBatch("");
+
+ // BAD: buffer too short
+ vm.expectRevert(ERC7579Utils.ERC7579DecodingError.selector);
+ this.callDecodeBatch(abi.encodePacked(uint128(0)));
+
+ // GOOD
+ this.callDecodeBatch(abi.encode(0));
+ // Note: Solidity also supports this even though it's odd. Offset 0 means array is at the same location, which
+ // is interpreted as an array of length 0, which doesn't require any more data
+ // solhint-disable-next-line var-name-mixedcase
+ uint256[] memory _1 = abi.decode(abi.encode(0), (uint256[]));
+ _1;
+
+ // BAD: offset is out of bounds
+ vm.expectRevert(ERC7579Utils.ERC7579DecodingError.selector);
+ this.callDecodeBatch(abi.encode(1));
+
+ // GOOD
+ this.callDecodeBatch(abi.encode(32, 0));
+
+ // BAD: reported array length extends beyond bounds
+ vm.expectRevert(ERC7579Utils.ERC7579DecodingError.selector);
+ this.callDecodeBatch(abi.encode(32, 1));
+
+ // GOOD
+ this.callDecodeBatch(abi.encode(32, 1, 0));
+
+ // GOOD
+ //
+ // 0000000000000000000000000000000000000000000000000000000000000020 (32) offset
+ // 0000000000000000000000000000000000000000000000000000000000000001 ( 1) array length
+ // 0000000000000000000000000000000000000000000000000000000000000020 (32) element 0 offset
+ // 000000000000000000000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (recipient) target for element #0
+ // 000000000000000000000000000000000000000000000000000000000000002a (42) value for element #0
+ // 0000000000000000000000000000000000000000000000000000000000000060 (96) offset to calldata for element #0
+ // 000000000000000000000000000000000000000000000000000000000000000c (12) length of the calldata for element #0
+ // 48656c6c6f20576f726c64210000000000000000000000000000000000000000 (..) buffer for the calldata for element #0
+ assertEq(
+ bytes("Hello World!"),
+ this.callDecodeBatchAndGetFirstBytes(
+ abi.encode(32, 1, 32, _recipient1, 42, 96, 12, bytes12("Hello World!"))
+ )
+ );
+
+ // This is invalid, the first element of the array points is out of bounds
+ // but we allow it past initial validation, because solidity will validate later when the bytes field is accessed
+ //
+ // 0000000000000000000000000000000000000000000000000000000000000020 (32) offset
+ // 0000000000000000000000000000000000000000000000000000000000000001 ( 1) array length
+ // 0000000000000000000000000000000000000000000000000000000000000020 (32) element 0 offset
+ //
+ bytes memory invalid = abi.encode(32, 1, 32);
+ this.callDecodeBatch(invalid);
+ vm.expectRevert();
+ this.callDecodeBatchAndGetFirst(invalid);
+
+ // this is invalid: the bytes field of the first element of the array is out of bounds
+ // but we allow it past initial validation, because solidity will validate later when the bytes field is accessed
+ //
+ // 0000000000000000000000000000000000000000000000000000000000000020 (32) offset
+ // 0000000000000000000000000000000000000000000000000000000000000001 ( 1) array length
+ // 0000000000000000000000000000000000000000000000000000000000000020 (32) element 0 offset
+ // 000000000000000000000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (recipient) target for element #0
+ // 000000000000000000000000000000000000000000000000000000000000002a (42) value for element #0
+ // 0000000000000000000000000000000000000000000000000000000000000060 (96) offset to calldata for element #0
+ //
+ bytes memory invalidDeeply = abi.encode(32, 1, 32, _recipient1, 42, 96);
+ this.callDecodeBatch(invalidDeeply);
+ // Note that this is ok because we don't return the value. Returning it would introduce a check that would fails.
+ this.callDecodeBatchAndGetFirst(invalidDeeply);
+ vm.expectRevert();
+ this.callDecodeBatchAndGetFirstBytes(invalidDeeply);
+ }
+
+ function callDecodeBatch(bytes calldata executionCalldata) public pure {
+ ERC7579Utils.decodeBatch(executionCalldata);
+ }
+
+ function callDecodeBatchAndGetFirst(bytes calldata executionCalldata) public pure {
+ ERC7579Utils.decodeBatch(executionCalldata)[0];
+ }
+
+ function callDecodeBatchAndGetFirstBytes(bytes calldata executionCalldata) public pure returns (bytes calldata) {
+ return ERC7579Utils.decodeBatch(executionCalldata)[0].callData;
+ }
+
+ function hashUserOperation(PackedUserOperation calldata useroperation) public view returns (bytes32) {
+ return useroperation.hash(address(ENTRYPOINT), block.chainid);
+ }
+
+ function _collectAndPrintLogs(bool includeTotalValue) internal {
+ Vm.Log[] memory logs = vm.getRecordedLogs();
+ for (uint256 i = 0; i < logs.length; i++) {
+ if (logs[i].emitter == _account) {
+ _printDecodedCalls(logs[i].data, includeTotalValue);
+ }
+ }
+ }
+
+ function _printDecodedCalls(bytes memory logData, bool includeTotalValue) internal pure {
+ (bool duringValidation, Execution[] memory calls) = abi.decode(logData, (bool, Execution[]));
+
+ console.log(
+ string.concat(
+ "Batch execute contents, as read during ",
+ duringValidation ? "validation" : "execution",
+ ": "
+ )
+ );
+ console.log(" Execution[] length: %s", calls.length);
+
+ uint256 totalValue = 0;
+ for (uint256 i = 0; i < calls.length; ++i) {
+ console.log(string.concat(" calls[", vm.toString(i), "].target = ", vm.toString(calls[i].target)));
+ console.log(string.concat(" calls[", vm.toString(i), "].value = ", vm.toString(calls[i].value)));
+ console.log(string.concat(" calls[", vm.toString(i), "].data = ", vm.toString(calls[i].callData)));
+ totalValue += calls[i].value;
+ }
+
+ if (includeTotalValue) {
+ console.log(" Total value: %s", totalValue);
+ }
+ }
+
+ function _packGas(uint256 upper, uint256 lower) internal pure returns (bytes32) {
+ return bytes32(uint256((upper << 128) | uint128(lower)));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.test.js
new file mode 100644
index 000000000..7419c667b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/account/utils/draft-ERC7579Utils.test.js
@@ -0,0 +1,353 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const {
+ EXEC_TYPE_DEFAULT,
+ EXEC_TYPE_TRY,
+ encodeSingle,
+ encodeBatch,
+ encodeDelegate,
+ CALL_TYPE_CALL,
+ CALL_TYPE_BATCH,
+ encodeMode,
+} = require('../../helpers/erc7579');
+const { selector } = require('../../helpers/methods');
+
+const coder = ethers.AbiCoder.defaultAbiCoder();
+
+const fixture = async () => {
+ const [sender] = await ethers.getSigners();
+ const utils = await ethers.deployContract('$ERC7579Utils', { value: ethers.parseEther('1') });
+ const utilsGlobal = await ethers.deployContract('$ERC7579UtilsGlobalMock');
+ const target = await ethers.deployContract('CallReceiverMock');
+ const anotherTarget = await ethers.deployContract('CallReceiverMock');
+ return { utils, utilsGlobal, target, anotherTarget, sender };
+};
+
+describe('ERC7579Utils', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('execSingle', function () {
+ it('calls the target with value', async function () {
+ const value = 0x012;
+ const data = encodeSingle(this.target, value, this.target.interface.encodeFunctionData('mockFunction'));
+
+ await expect(this.utils.$execSingle(data, EXEC_TYPE_DEFAULT)).to.emit(this.target, 'MockFunctionCalled');
+
+ expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value);
+ });
+
+ it('calls the target with value and args', async function () {
+ const value = 0x432;
+ const data = encodeSingle(
+ this.target,
+ value,
+ this.target.interface.encodeFunctionData('mockFunctionWithArgs', [42, '0x1234']),
+ );
+
+ await expect(this.utils.$execSingle(data, EXEC_TYPE_DEFAULT))
+ .to.emit(this.target, 'MockFunctionCalledWithArgs')
+ .withArgs(42, '0x1234');
+
+ expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value);
+ });
+
+ it('reverts when target reverts in default ExecType', async function () {
+ const value = 0x012;
+ const data = encodeSingle(
+ this.target,
+ value,
+ this.target.interface.encodeFunctionData('mockFunctionRevertsReason'),
+ );
+
+ await expect(this.utils.$execSingle(data, EXEC_TYPE_DEFAULT)).to.be.revertedWith('CallReceiverMock: reverting');
+ });
+
+ it('emits ERC7579TryExecuteFail event when target reverts in try ExecType', async function () {
+ const value = 0x012;
+ const data = encodeSingle(
+ this.target,
+ value,
+ this.target.interface.encodeFunctionData('mockFunctionRevertsReason'),
+ );
+
+ await expect(this.utils.$execSingle(data, EXEC_TYPE_TRY))
+ .to.emit(this.utils, 'ERC7579TryExecuteFail')
+ .withArgs(
+ CALL_TYPE_CALL,
+ ethers.solidityPacked(
+ ['bytes4', 'bytes'],
+ [selector('Error(string)'), coder.encode(['string'], ['CallReceiverMock: reverting'])],
+ ),
+ );
+ });
+
+ it('reverts with an invalid exec type', async function () {
+ const value = 0x012;
+ const data = encodeSingle(this.target, value, this.target.interface.encodeFunctionData('mockFunction'));
+
+ await expect(this.utils.$execSingle(data, '0x03'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC7579UnsupportedExecType')
+ .withArgs('0x03');
+ });
+ });
+
+ describe('execBatch', function () {
+ it('calls the targets with value', async function () {
+ const value1 = 0x012;
+ const value2 = 0x234;
+ const data = encodeBatch(
+ [this.target, value1, this.target.interface.encodeFunctionData('mockFunction')],
+ [this.anotherTarget, value2, this.anotherTarget.interface.encodeFunctionData('mockFunction')],
+ );
+
+ await expect(this.utils.$execBatch(data, EXEC_TYPE_DEFAULT))
+ .to.emit(this.target, 'MockFunctionCalled')
+ .to.emit(this.anotherTarget, 'MockFunctionCalled');
+
+ expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1);
+ expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2);
+ });
+
+ it('calls the targets with value and args', async function () {
+ const value1 = 0x012;
+ const value2 = 0x234;
+ const data = encodeBatch(
+ [this.target, value1, this.target.interface.encodeFunctionData('mockFunctionWithArgs', [42, '0x1234'])],
+ [
+ this.anotherTarget,
+ value2,
+ this.anotherTarget.interface.encodeFunctionData('mockFunctionWithArgs', [42, '0x1234']),
+ ],
+ );
+
+ await expect(this.utils.$execBatch(data, EXEC_TYPE_DEFAULT))
+ .to.emit(this.target, 'MockFunctionCalledWithArgs')
+ .to.emit(this.anotherTarget, 'MockFunctionCalledWithArgs');
+
+ expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1);
+ expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2);
+ });
+
+ it('reverts when any target reverts in default ExecType', async function () {
+ const value1 = 0x012;
+ const value2 = 0x234;
+ const data = encodeBatch(
+ [this.target, value1, this.target.interface.encodeFunctionData('mockFunction')],
+ [this.anotherTarget, value2, this.anotherTarget.interface.encodeFunctionData('mockFunctionRevertsReason')],
+ );
+
+ await expect(this.utils.$execBatch(data, EXEC_TYPE_DEFAULT)).to.be.revertedWith('CallReceiverMock: reverting');
+ });
+
+ it('emits ERC7579TryExecuteFail event when any target reverts in try ExecType', async function () {
+ const value1 = 0x012;
+ const value2 = 0x234;
+ const data = encodeBatch(
+ [this.target, value1, this.target.interface.encodeFunctionData('mockFunction')],
+ [this.anotherTarget, value2, this.anotherTarget.interface.encodeFunctionData('mockFunctionRevertsReason')],
+ );
+
+ await expect(this.utils.$execBatch(data, EXEC_TYPE_TRY))
+ .to.emit(this.utils, 'ERC7579TryExecuteFail')
+ .withArgs(
+ CALL_TYPE_BATCH,
+ ethers.solidityPacked(
+ ['bytes4', 'bytes'],
+ [selector('Error(string)'), coder.encode(['string'], ['CallReceiverMock: reverting'])],
+ ),
+ );
+
+ // Check balances
+ expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value1);
+ expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(0);
+ });
+
+ it('reverts with an invalid exec type', async function () {
+ const value1 = 0x012;
+ const value2 = 0x234;
+ const data = encodeBatch(
+ [this.target, value1, this.target.interface.encodeFunctionData('mockFunction')],
+ [this.anotherTarget, value2, this.anotherTarget.interface.encodeFunctionData('mockFunction')],
+ );
+
+ await expect(this.utils.$execBatch(data, '0x03'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC7579UnsupportedExecType')
+ .withArgs('0x03');
+ });
+ });
+
+ describe('execDelegateCall', function () {
+ it('delegate calls the target', async function () {
+ const slot = ethers.hexlify(ethers.randomBytes(32));
+ const value = ethers.hexlify(ethers.randomBytes(32));
+ const data = encodeDelegate(
+ this.target,
+ this.target.interface.encodeFunctionData('mockFunctionWritesStorage', [slot, value]),
+ );
+
+ expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(ethers.ZeroHash);
+ await this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT);
+ expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(value);
+ });
+
+ it('reverts when target reverts in default ExecType', async function () {
+ const data = encodeDelegate(this.target, this.target.interface.encodeFunctionData('mockFunctionRevertsReason'));
+ await expect(this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT)).to.be.revertedWith(
+ 'CallReceiverMock: reverting',
+ );
+ });
+
+ it('emits ERC7579TryExecuteFail event when target reverts in try ExecType', async function () {
+ const data = encodeDelegate(this.target, this.target.interface.encodeFunctionData('mockFunctionRevertsReason'));
+ await expect(this.utils.$execDelegateCall(data, EXEC_TYPE_TRY))
+ .to.emit(this.utils, 'ERC7579TryExecuteFail')
+ .withArgs(
+ CALL_TYPE_CALL,
+ ethers.solidityPacked(
+ ['bytes4', 'bytes'],
+ [selector('Error(string)'), coder.encode(['string'], ['CallReceiverMock: reverting'])],
+ ),
+ );
+ });
+
+ it('reverts with an invalid exec type', async function () {
+ const data = encodeDelegate(this.target, this.target.interface.encodeFunctionData('mockFunction'));
+ await expect(this.utils.$execDelegateCall(data, '0x03'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC7579UnsupportedExecType')
+ .withArgs('0x03');
+ });
+ });
+
+ it('encodes Mode', async function () {
+ const callType = CALL_TYPE_BATCH;
+ const execType = EXEC_TYPE_TRY;
+ const selector = '0x12345678';
+ const payload = ethers.toBeHex(0, 22);
+
+ expect(this.utils.$encodeMode(callType, execType, selector, payload)).to.eventually.equal(
+ encodeMode({
+ callType,
+ execType,
+ selector,
+ payload,
+ }),
+ );
+ });
+
+ it('decodes Mode', async function () {
+ const callType = CALL_TYPE_BATCH;
+ const execType = EXEC_TYPE_TRY;
+ const selector = '0x12345678';
+ const payload = ethers.toBeHex(0, 22);
+
+ expect(
+ this.utils.$decodeMode(
+ encodeMode({
+ callType,
+ execType,
+ selector,
+ payload,
+ }),
+ ),
+ ).to.eventually.deep.equal([callType, execType, selector, payload]);
+ });
+
+ it('encodes single', async function () {
+ const target = this.target;
+ const value = 0x123;
+ const data = '0x12345678';
+
+ expect(this.utils.$encodeSingle(target, value, data)).to.eventually.equal(encodeSingle(target, value, data));
+ });
+
+ it('decodes single', async function () {
+ const target = this.target;
+ const value = 0x123;
+ const data = '0x12345678';
+
+ expect(this.utils.$decodeSingle(encodeSingle(target, value, data))).to.eventually.deep.equal([
+ target.target,
+ value,
+ data,
+ ]);
+ });
+
+ it('encodes batch', async function () {
+ const entries = [
+ [this.target, 0x123, '0x12345678'],
+ [this.anotherTarget, 0x456, '0x12345678'],
+ ];
+
+ expect(this.utils.$encodeBatch(entries)).to.eventually.equal(encodeBatch(...entries));
+ });
+
+ it('decodes batch', async function () {
+ const entries = [
+ [this.target.target, 0x123, '0x12345678'],
+ [this.anotherTarget.target, 0x456, '0x12345678'],
+ ];
+
+ expect(this.utils.$decodeBatch(encodeBatch(...entries))).to.eventually.deep.equal(entries);
+ });
+
+ it('encodes delegate', async function () {
+ const target = this.target;
+ const data = '0x12345678';
+
+ expect(this.utils.$encodeDelegate(target, data)).to.eventually.equal(encodeDelegate(target, data));
+ });
+
+ it('decodes delegate', async function () {
+ const target = this.target;
+ const data = '0x12345678';
+
+ expect(this.utils.$decodeDelegate(encodeDelegate(target, data))).to.eventually.deep.equal([target.target, data]);
+ });
+
+ describe('global', function () {
+ describe('eqCallTypeGlobal', function () {
+ it('returns true if both call types are equal', async function () {
+ expect(this.utilsGlobal.$eqCallTypeGlobal(CALL_TYPE_BATCH, CALL_TYPE_BATCH)).to.eventually.be.true;
+ });
+
+ it('returns false if both call types are different', async function () {
+ expect(this.utilsGlobal.$eqCallTypeGlobal(CALL_TYPE_CALL, CALL_TYPE_BATCH)).to.eventually.be.false;
+ });
+ });
+
+ describe('eqExecTypeGlobal', function () {
+ it('returns true if both exec types are equal', async function () {
+ expect(this.utilsGlobal.$eqExecTypeGlobal(EXEC_TYPE_TRY, EXEC_TYPE_TRY)).to.eventually.be.true;
+ });
+
+ it('returns false if both exec types are different', async function () {
+ expect(this.utilsGlobal.$eqExecTypeGlobal(EXEC_TYPE_DEFAULT, EXEC_TYPE_TRY)).to.eventually.be.false;
+ });
+ });
+
+ describe('eqModeSelectorGlobal', function () {
+ it('returns true if both selectors are equal', async function () {
+ expect(this.utilsGlobal.$eqModeSelectorGlobal('0x12345678', '0x12345678')).to.eventually.be.true;
+ });
+
+ it('returns false if both selectors are different', async function () {
+ expect(this.utilsGlobal.$eqModeSelectorGlobal('0x12345678', '0x87654321')).to.eventually.be.false;
+ });
+ });
+
+ describe('eqModePayloadGlobal', function () {
+ it('returns true if both payloads are equal', async function () {
+ expect(this.utilsGlobal.$eqModePayloadGlobal(ethers.toBeHex(0, 22), ethers.toBeHex(0, 22))).to.eventually.be
+ .true;
+ });
+
+ it('returns false if both payloads are different', async function () {
+ expect(this.utilsGlobal.$eqModePayloadGlobal(ethers.toBeHex(0, 22), ethers.toBeHex(1, 22))).to.eventually.be
+ .false;
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/EntryPoint070.abi b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/EntryPoint070.abi
new file mode 100644
index 000000000..3f3b1d6e5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/EntryPoint070.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"name":"DelegateAndRevert","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"FailedOp","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"inner","type":"bytes"}],"name":"FailedOpWithRevert","type":"error"},{"inputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"PostOpReverted","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderAddressResult","type":"error"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureValidationFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"address","name":"paymaster","type":"address"}],"name":"AccountDeployed","type":"event"},{"anonymous":false,"inputs":[],"name":"BeforeExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalDeposit","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"PostOpRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureAggregatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalStaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawTime","type":"uint256"}],"name":"StakeUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"paymaster","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"actualGasCost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualGasUsed","type":"uint256"}],"name":"UserOperationEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"UserOperationPrefundTooLow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"UserOperationRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"delegateAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"bool","name":"staked","type":"bool"},{"internalType":"uint112","name":"stake","type":"uint112"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"},{"internalType":"uint48","name":"withdrawTime","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getDepositInfo","outputs":[{"components":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"bool","name":"staked","type":"bool"},{"internalType":"uint112","name":"stake","type":"uint112"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"},{"internalType":"uint48","name":"withdrawTime","type":"uint48"}],"internalType":"struct IStakeManager.DepositInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint192","name":"key","type":"uint192"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"getSenderAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"userOp","type":"tuple"}],"name":"getUserOpHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"userOps","type":"tuple[]"},{"internalType":"contract IAggregator","name":"aggregator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IEntryPoint.UserOpsPerAggregator[]","name":"opsPerAggregator","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleAggregatedOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"ops","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"key","type":"uint192"}],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"address","name":"paymaster","type":"address"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"}],"internalType":"struct EntryPoint.MemoryUserOp","name":"mUserOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"contextOffset","type":"uint256"},{"internalType":"uint256","name":"preOpGas","type":"uint256"}],"internalType":"struct EntryPoint.UserOpInfo","name":"opInfo","type":"tuple"},{"internalType":"bytes","name":"context","type":"bytes"}],"name":"innerHandleOp","outputs":[{"internalType":"uint256","name":"actualGasCost","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint192","name":"","type":"uint192"}],"name":"nonceSequenceNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/EntryPoint070.bytecode b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/EntryPoint070.bytecode
new file mode 100644
index 000000000..fce261af5
Binary files /dev/null and b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/EntryPoint070.bytecode differ
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/SenderCreator070.abi b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/SenderCreator070.abi
new file mode 100644
index 000000000..0a1f0e4fb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/SenderCreator070.abi
@@ -0,0 +1 @@
+[{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"createSender","outputs":[{"internalType":"address","name":"sender","type":"address"}],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/SenderCreator070.bytecode b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/SenderCreator070.bytecode
new file mode 100644
index 000000000..8344c2028
Binary files /dev/null and b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/bin/SenderCreator070.bytecode differ
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWallet.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWallet.behavior.js
new file mode 100644
index 000000000..b45ffeecf
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWallet.behavior.js
@@ -0,0 +1,87 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const time = require('../helpers/time');
+
+async function envSetup(mock, beneficiary, token) {
+ return {
+ eth: {
+ checkRelease: async (tx, amount) => {
+ await expect(tx).to.changeEtherBalances([mock, beneficiary], [-amount, amount]);
+ },
+ setupFailure: async () => {
+ const beneficiaryMock = await ethers.deployContract('EtherReceiverMock');
+ await beneficiaryMock.setAcceptEther(false);
+ await mock.connect(beneficiary).transferOwnership(beneficiaryMock);
+ return { args: [], error: [mock, 'FailedCall'] };
+ },
+ releasedEvent: 'EtherReleased',
+ args: [],
+ },
+ token: {
+ checkRelease: async (tx, amount) => {
+ await expect(tx).to.emit(token, 'Transfer').withArgs(mock, beneficiary, amount);
+ await expect(tx).to.changeTokenBalances(token, [mock, beneficiary], [-amount, amount]);
+ },
+ setupFailure: async () => {
+ const pausableToken = await ethers.deployContract('$ERC20Pausable', ['Name', 'Symbol']);
+ await pausableToken.$_pause();
+ return {
+ args: [ethers.Typed.address(pausableToken)],
+ error: [pausableToken, 'EnforcedPause'],
+ };
+ },
+ releasedEvent: 'ERC20Released',
+ args: [ethers.Typed.address(token)],
+ },
+ };
+}
+
+function shouldBehaveLikeVesting() {
+ it('check vesting schedule', async function () {
+ for (const timestamp of this.schedule) {
+ await time.increaseTo.timestamp(timestamp);
+ const vesting = this.vestingFn(timestamp);
+
+ expect(await this.mock.vestedAmount(...this.args, timestamp)).to.equal(vesting);
+ expect(await this.mock.releasable(...this.args)).to.equal(vesting);
+ }
+ });
+
+ it('execute vesting schedule', async function () {
+ let released = 0n;
+ {
+ const tx = await this.mock.release(...this.args);
+ await expect(tx)
+ .to.emit(this.mock, this.releasedEvent)
+ .withArgs(...this.args, 0);
+
+ await this.checkRelease(tx, 0n);
+ }
+
+ for (const timestamp of this.schedule) {
+ await time.increaseTo.timestamp(timestamp, false);
+ const vested = this.vestingFn(timestamp);
+
+ const tx = await this.mock.release(...this.args);
+ await expect(tx).to.emit(this.mock, this.releasedEvent);
+
+ await this.checkRelease(tx, vested - released);
+ released = vested;
+ }
+ });
+
+ it('should revert on transaction failure', async function () {
+ const { args, error } = await this.setupFailure();
+
+ for (const timestamp of this.schedule) {
+ await time.increaseTo.timestamp(timestamp);
+
+ await expect(this.mock.release(...args)).to.be.revertedWithCustomError(...error);
+ }
+ });
+}
+
+module.exports = {
+ envSetup,
+ shouldBehaveLikeVesting,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWallet.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWallet.test.js
new file mode 100644
index 000000000..b89258d65
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWallet.test.js
@@ -0,0 +1,65 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { min } = require('../helpers/math');
+const time = require('../helpers/time');
+
+const { envSetup, shouldBehaveLikeVesting } = require('./VestingWallet.behavior');
+
+async function fixture() {
+ const amount = ethers.parseEther('100');
+ const duration = time.duration.years(4);
+ const start = (await time.clock.timestamp()) + time.duration.hours(1);
+
+ const [sender, beneficiary] = await ethers.getSigners();
+ const mock = await ethers.deployContract('VestingWallet', [beneficiary, start, duration]);
+
+ const token = await ethers.deployContract('$ERC20', ['Name', 'Symbol']);
+ await token.$_mint(mock, amount);
+ await sender.sendTransaction({ to: mock, value: amount });
+
+ const env = await envSetup(mock, beneficiary, token);
+
+ const schedule = Array.from({ length: 64 }, (_, i) => (BigInt(i) * duration) / 60n + start);
+ const vestingFn = timestamp => min(amount, (amount * (timestamp - start)) / duration);
+
+ return { mock, duration, start, beneficiary, schedule, vestingFn, env };
+}
+
+describe('VestingWallet', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('rejects zero address for beneficiary', async function () {
+ await expect(ethers.deployContract('VestingWallet', [ethers.ZeroAddress, this.start, this.duration]))
+ .revertedWithCustomError(this.mock, 'OwnableInvalidOwner')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('check vesting contract', async function () {
+ expect(await this.mock.owner()).to.equal(this.beneficiary);
+ expect(await this.mock.start()).to.equal(this.start);
+ expect(await this.mock.duration()).to.equal(this.duration);
+ expect(await this.mock.end()).to.equal(this.start + this.duration);
+ });
+
+ describe('vesting schedule', function () {
+ describe('Eth vesting', function () {
+ beforeEach(async function () {
+ Object.assign(this, this.env.eth);
+ });
+
+ shouldBehaveLikeVesting();
+ });
+
+ describe('ERC20 vesting', function () {
+ beforeEach(async function () {
+ Object.assign(this, this.env.token);
+ });
+
+ shouldBehaveLikeVesting();
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWalletCliff.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWalletCliff.test.js
new file mode 100644
index 000000000..799b24c4b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/finance/VestingWalletCliff.test.js
@@ -0,0 +1,70 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { min } = require('../helpers/math');
+const time = require('../helpers/time');
+
+const { envSetup, shouldBehaveLikeVesting } = require('./VestingWallet.behavior');
+
+async function fixture() {
+ const amount = ethers.parseEther('100');
+ const duration = time.duration.years(4);
+ const start = (await time.clock.timestamp()) + time.duration.hours(1);
+ const cliffDuration = time.duration.years(1);
+ const cliff = start + cliffDuration;
+
+ const [sender, beneficiary] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$VestingWalletCliff', [beneficiary, start, duration, cliffDuration]);
+
+ const token = await ethers.deployContract('$ERC20', ['Name', 'Symbol']);
+ await token.$_mint(mock, amount);
+ await sender.sendTransaction({ to: mock, value: amount });
+
+ const env = await envSetup(mock, beneficiary, token);
+
+ const schedule = Array.from({ length: 64 }, (_, i) => (BigInt(i) * duration) / 60n + start);
+ const vestingFn = timestamp => min(amount, timestamp < cliff ? 0n : (amount * (timestamp - start)) / duration);
+
+ return { mock, duration, start, beneficiary, cliff, schedule, vestingFn, env };
+}
+
+describe('VestingWalletCliff', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('rejects a larger cliff than vesting duration', async function () {
+ await expect(
+ ethers.deployContract('$VestingWalletCliff', [this.beneficiary, this.start, this.duration, this.duration + 1n]),
+ )
+ .revertedWithCustomError(this.mock, 'InvalidCliffDuration')
+ .withArgs(this.duration + 1n, this.duration);
+ });
+
+ it('check vesting contract', async function () {
+ expect(await this.mock.owner()).to.equal(this.beneficiary);
+ expect(await this.mock.start()).to.equal(this.start);
+ expect(await this.mock.duration()).to.equal(this.duration);
+ expect(await this.mock.end()).to.equal(this.start + this.duration);
+ expect(await this.mock.cliff()).to.equal(this.cliff);
+ });
+
+ describe('vesting schedule', function () {
+ describe('Eth vesting', function () {
+ beforeEach(async function () {
+ Object.assign(this, this.env.eth);
+ });
+
+ shouldBehaveLikeVesting();
+ });
+
+ describe('ERC20 vesting', function () {
+ beforeEach(async function () {
+ Object.assign(this, this.env.token);
+ });
+
+ shouldBehaveLikeVesting();
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/Governor.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/Governor.t.sol
new file mode 100644
index 000000000..958461abb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/Governor.t.sol
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
+import {Governor} from "@openzeppelin/contracts/governance/Governor.sol";
+
+contract GovernorInternalTest is Test, Governor {
+ constructor() Governor("") {}
+
+ function testValidDescriptionForProposer(string memory description, address proposer, bool includeProposer) public {
+ if (includeProposer) {
+ description = string.concat(description, "#proposer=", Strings.toHexString(proposer));
+ }
+ assertTrue(_isValidDescriptionForProposer(proposer, description));
+ }
+
+ function testInvalidDescriptionForProposer(
+ string memory description,
+ address commitProposer,
+ address actualProposer
+ ) public {
+ vm.assume(commitProposer != actualProposer);
+ description = string.concat(description, "#proposer=", Strings.toHexString(commitProposer));
+ assertFalse(_isValidDescriptionForProposer(actualProposer, description));
+ }
+
+ // We don't need to truly implement the missing functions because we are just testing
+ // internal helpers.
+
+ function clock() public pure override returns (uint48) {}
+
+ // solhint-disable-next-line func-name-mixedcase
+ function CLOCK_MODE() public pure override returns (string memory) {}
+
+ // solhint-disable-next-line func-name-mixedcase
+ function COUNTING_MODE() public pure virtual override returns (string memory) {}
+
+ function votingDelay() public pure virtual override returns (uint256) {}
+
+ function votingPeriod() public pure virtual override returns (uint256) {}
+
+ function quorum(uint256) public pure virtual override returns (uint256) {}
+
+ function hasVoted(uint256, address) public pure virtual override returns (bool) {}
+
+ function _quorumReached(uint256) internal pure virtual override returns (bool) {}
+
+ function _voteSucceeded(uint256) internal pure virtual override returns (bool) {}
+
+ function _getVotes(address, uint256, bytes memory) internal pure virtual override returns (uint256) {}
+
+ function _countVote(uint256, address, uint8, uint256, bytes memory) internal virtual override returns (uint256) {}
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/Governor.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/Governor.test.js
new file mode 100644
index 000000000..3e48ccfee
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/Governor.test.js
@@ -0,0 +1,992 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../helpers/governance');
+const { getDomain, Ballot } = require('../helpers/eip712');
+const { ProposalState, VoteType } = require('../helpers/enums');
+const time = require('../helpers/time');
+
+const { shouldSupportInterfaces } = require('../utils/introspection/SupportsInterface.behavior');
+const { shouldBehaveLikeERC6372 } = require('./utils/ERC6372.behavior');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+ { Token: '$ERC20VotesLegacyMock', mode: 'blocknumber' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+const signBallot = account => (contract, message) =>
+ getDomain(contract).then(domain => account.signTypedData(domain, { Ballot }, message));
+
+async function deployToken(contractName) {
+ try {
+ return await ethers.deployContract(contractName, [tokenName, tokenSymbol, tokenName, version]);
+ } catch (error) {
+ if (error.message == 'incorrect number of arguments to constructor') {
+ // ERC20VotesLegacyMock has a different construction that uses version='1' by default.
+ return ethers.deployContract(contractName, [tokenName, tokenSymbol, tokenName]);
+ }
+ throw error;
+ }
+}
+
+describe('Governor', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, proposer, voter1, voter2, voter3, voter4, userEOA] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await deployToken(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorMock', [
+ name, // name
+ votingDelay, // initialVotingDelay
+ votingPeriod, // initialVotingPeriod
+ 0n, // initialProposalThreshold
+ token, // tokenAddress
+ 10n, // quorumNumeratorValue
+ ]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token: token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token: token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token: token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token: token, to: voter4, value: ethers.parseEther('2') });
+
+ return {
+ owner,
+ proposer,
+ voter1,
+ voter2,
+ voter3,
+ voter4,
+ userEOA,
+ receiver,
+ token,
+ mock,
+ helper,
+ };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ // initiate fresh proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ '',
+ );
+ });
+
+ shouldSupportInterfaces(['ERC1155Receiver', 'Governor']);
+ shouldBehaveLikeERC6372(mode);
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0)).to.equal(0n);
+ expect(await this.mock.COUNTING_MODE()).to.equal('support=bravo&quorum=for,abstain');
+ });
+
+ it('nominal workflow', async function () {
+ // Before
+ expect(await this.mock.proposalProposer(this.proposal.id)).to.equal(ethers.ZeroAddress);
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.false;
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(value);
+ expect(await ethers.provider.getBalance(this.receiver)).to.equal(0n);
+
+ expect(await this.mock.proposalEta(this.proposal.id)).to.equal(0n);
+ expect(await this.mock.proposalNeedsQueuing(this.proposal.id)).to.be.false;
+
+ // Run proposal
+ const txPropose = await this.helper.connect(this.proposer).propose();
+ const timepoint = await time.clockFromReceipt[mode](txPropose);
+
+ await expect(txPropose)
+ .to.emit(this.mock, 'ProposalCreated')
+ .withArgs(
+ this.proposal.id,
+ this.proposer,
+ this.proposal.targets,
+ this.proposal.values,
+ this.proposal.signatures,
+ this.proposal.data,
+ timepoint + votingDelay,
+ timepoint + votingDelay + votingPeriod,
+ this.proposal.description,
+ );
+
+ await this.helper.waitForSnapshot();
+
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For, reason: 'This is nice' }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter1, this.proposal.id, VoteType.For, ethers.parseEther('10'), 'This is nice');
+
+ await expect(this.helper.connect(this.voter2).vote({ support: VoteType.For }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter2, this.proposal.id, VoteType.For, ethers.parseEther('7'), '');
+
+ await expect(this.helper.connect(this.voter3).vote({ support: VoteType.Against }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter3, this.proposal.id, VoteType.Against, ethers.parseEther('5'), '');
+
+ await expect(this.helper.connect(this.voter4).vote({ support: VoteType.Abstain }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter4, this.proposal.id, VoteType.Abstain, ethers.parseEther('2'), '');
+
+ await this.helper.waitForDeadline();
+
+ const txExecute = await this.helper.execute();
+
+ await expect(txExecute).to.emit(this.mock, 'ProposalExecuted').withArgs(this.proposal.id);
+
+ await expect(txExecute).to.emit(this.receiver, 'MockFunctionCalled');
+
+ // After
+ expect(await this.mock.proposalProposer(this.proposal.id)).to.equal(this.proposer);
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.true;
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.receiver)).to.equal(value);
+
+ expect(await this.mock.proposalEta(this.proposal.id)).to.equal(0n);
+ expect(await this.mock.proposalNeedsQueuing(this.proposal.id)).to.be.false;
+ });
+
+ it('send ethers', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.userEOA.address,
+ value,
+ },
+ ],
+ '',
+ );
+
+ // Run proposal
+ await expect(async () => {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ return this.helper.execute();
+ }).to.changeEtherBalances([this.mock, this.userEOA], [-value, value]);
+ });
+
+ describe('vote with signature', function () {
+ it('votes with an EOA signature', async function () {
+ await this.token.connect(this.voter1).delegate(this.userEOA);
+
+ const nonce = await this.mock.nonces(this.userEOA);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await expect(
+ this.helper.vote({
+ support: VoteType.For,
+ voter: this.userEOA.address,
+ nonce,
+ signature: signBallot(this.userEOA),
+ }),
+ )
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.userEOA, this.proposal.id, VoteType.For, ethers.parseEther('10'), '');
+
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ // After
+ expect(await this.mock.hasVoted(this.proposal.id, this.userEOA)).to.be.true;
+ expect(await this.mock.nonces(this.userEOA)).to.equal(nonce + 1n);
+ });
+
+ it('votes with a valid EIP-1271 signature', async function () {
+ const wallet = await ethers.deployContract('ERC1271WalletMock', [this.userEOA]);
+
+ await this.token.connect(this.voter1).delegate(wallet);
+
+ const nonce = await this.mock.nonces(this.userEOA);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await expect(
+ this.helper.vote({
+ support: VoteType.For,
+ voter: wallet.target,
+ nonce,
+ signature: signBallot(this.userEOA),
+ }),
+ )
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(wallet, this.proposal.id, VoteType.For, ethers.parseEther('10'), '');
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ // After
+ expect(await this.mock.hasVoted(this.proposal.id, wallet)).to.be.true;
+ expect(await this.mock.nonces(wallet)).to.equal(nonce + 1n);
+ });
+
+ afterEach('no other votes are cast', async function () {
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.false;
+ });
+ });
+
+ describe('should revert', function () {
+ describe('on propose', function () {
+ it('if proposal already exists', async function () {
+ await this.helper.propose();
+ await expect(this.helper.propose())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(this.proposal.id, ProposalState.Pending, ethers.ZeroHash);
+ });
+
+ it('if proposer has below threshold votes', async function () {
+ const votes = ethers.parseEther('10');
+ const threshold = ethers.parseEther('1000');
+ await this.mock.$_setProposalThreshold(threshold);
+ await expect(this.helper.connect(this.voter1).propose())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInsufficientProposerVotes')
+ .withArgs(this.voter1, votes, threshold);
+ });
+ });
+
+ describe('on vote', function () {
+ it('if proposal does not exist', async function () {
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For }))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNonexistentProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('if voting has not started', async function () {
+ await this.helper.propose();
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For }))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Pending,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Active]),
+ );
+ });
+
+ it('if support value is invalid', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await expect(this.helper.vote({ support: 255 })).to.be.revertedWithCustomError(
+ this.mock,
+ 'GovernorInvalidVoteType',
+ );
+ });
+
+ it('if vote was already casted', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For }))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyCastVote')
+ .withArgs(this.voter1);
+ });
+
+ it('if voting is over', async function () {
+ await this.helper.propose();
+ await this.helper.waitForDeadline();
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For }))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Defeated,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Active]),
+ );
+ });
+ });
+
+ describe('on vote by signature', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.voter1).delegate(this.userEOA);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ });
+
+ it('if signature does not match signer', async function () {
+ const nonce = await this.mock.nonces(this.userEOA);
+
+ function tamper(str, index, mask) {
+ const arrayStr = ethers.getBytes(str);
+ arrayStr[index] ^= mask;
+ return ethers.hexlify(arrayStr);
+ }
+
+ const voteParams = {
+ support: VoteType.For,
+ voter: this.userEOA.address,
+ nonce,
+ signature: (...args) => signBallot(this.userEOA)(...args).then(sig => tamper(sig, 42, 0xff)),
+ };
+
+ await expect(this.helper.vote(voteParams))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSignature')
+ .withArgs(voteParams.voter);
+ });
+
+ it('if vote nonce is incorrect', async function () {
+ const nonce = await this.mock.nonces(this.userEOA);
+
+ const voteParams = {
+ support: VoteType.For,
+ voter: this.userEOA.address,
+ nonce: nonce + 1n,
+ signature: signBallot(this.userEOA),
+ };
+
+ await expect(this.helper.vote(voteParams))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSignature')
+ .withArgs(voteParams.voter);
+ });
+ });
+
+ describe('on queue', function () {
+ it('always', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await expect(this.helper.queue()).to.be.revertedWithCustomError(this.mock, 'GovernorQueueNotImplemented');
+ });
+ });
+
+ describe('on execute', function () {
+ it('if proposal does not exist', async function () {
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNonexistentProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('if quorum is not reached', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter3).vote({ support: VoteType.For });
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Active,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('if score not reached', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.Against });
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Active,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('if voting is not over', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Active,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('if receiver revert without reason', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunctionRevertsNoReason'),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await expect(this.helper.execute()).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+ });
+
+ it('if receiver revert with reason', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunctionRevertsReason'),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await expect(this.helper.execute()).to.be.revertedWith('CallReceiverMock: reverting');
+ });
+
+ it('if proposal was already executed', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Executed,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+ });
+ });
+
+ describe('state', function () {
+ it('Unset', async function () {
+ await expect(this.mock.state(this.proposal.id))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNonexistentProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('Pending & Active', async function () {
+ await this.helper.propose();
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Pending);
+ await this.helper.waitForSnapshot();
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Pending);
+ await this.helper.waitForSnapshot(1n);
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Active);
+ });
+
+ it('Defeated', async function () {
+ await this.helper.propose();
+ await this.helper.waitForDeadline();
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Active);
+ await this.helper.waitForDeadline(1n);
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Defeated);
+ });
+
+ it('Succeeded', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Active);
+ await this.helper.waitForDeadline(1n);
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Succeeded);
+ });
+
+ it('Executed', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Executed);
+ });
+ });
+
+ describe('cancel', function () {
+ describe('internal', function () {
+ it('before proposal', async function () {
+ await expect(this.helper.cancel('internal'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNonexistentProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('after proposal', async function () {
+ await this.helper.propose();
+
+ await this.helper.cancel('internal');
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await this.helper.waitForSnapshot();
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For }))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Active]),
+ );
+ });
+
+ it('after vote', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+
+ await this.helper.cancel('internal');
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await this.helper.waitForDeadline();
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('after deadline', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await this.helper.cancel('internal');
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('after execution', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ await expect(this.helper.cancel('internal'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Executed,
+ GovernorHelper.proposalStatesToBitMap(
+ [ProposalState.Canceled, ProposalState.Expired, ProposalState.Executed],
+ { inverted: true },
+ ),
+ );
+ });
+ });
+
+ describe('public', function () {
+ it('before proposal', async function () {
+ await expect(this.helper.cancel('external'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNonexistentProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('after proposal', async function () {
+ await this.helper.propose();
+
+ await this.helper.cancel('external');
+ });
+
+ it('after proposal - restricted to proposer', async function () {
+ await this.helper.connect(this.proposer).propose();
+
+ await expect(this.helper.connect(this.owner).cancel('external'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyProposer')
+ .withArgs(this.owner);
+ });
+
+ it('after vote started', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot(1n); // snapshot + 1 block
+
+ await expect(this.helper.cancel('external'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Active,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
+ );
+ });
+
+ it('after vote', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+
+ await expect(this.helper.cancel('external'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Active,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
+ );
+ });
+
+ it('after deadline', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.cancel('external'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Succeeded,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
+ );
+ });
+
+ it('after execution', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ await expect(this.helper.cancel('external'))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Executed,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Pending]),
+ );
+ });
+ });
+ });
+
+ describe('proposal length', function () {
+ it('empty', async function () {
+ this.helper.setProposal([], '');
+
+ await expect(this.helper.propose())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidProposalLength')
+ .withArgs(0, 0, 0);
+ });
+
+ it('mismatch #1', async function () {
+ this.helper.setProposal(
+ {
+ targets: [],
+ values: [0n],
+ data: [this.receiver.interface.encodeFunctionData('mockFunction')],
+ },
+ '',
+ );
+ await expect(this.helper.propose())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidProposalLength')
+ .withArgs(0, 1, 1);
+ });
+
+ it('mismatch #2', async function () {
+ this.helper.setProposal(
+ {
+ targets: [this.receiver.target],
+ values: [],
+ data: [this.receiver.interface.encodeFunctionData('mockFunction')],
+ },
+ '',
+ );
+ await expect(this.helper.propose())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidProposalLength')
+ .withArgs(1, 1, 0);
+ });
+
+ it('mismatch #3', async function () {
+ this.helper.setProposal(
+ {
+ targets: [this.receiver.target],
+ values: [0n],
+ data: [],
+ },
+ '',
+ );
+ await expect(this.helper.propose())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidProposalLength')
+ .withArgs(1, 0, 1);
+ });
+ });
+
+ describe('frontrun protection using description suffix', function () {
+ function shouldPropose() {
+ it('proposer can propose', async function () {
+ const txPropose = await this.helper.connect(this.proposer).propose();
+
+ await expect(txPropose)
+ .to.emit(this.mock, 'ProposalCreated')
+ .withArgs(
+ this.proposal.id,
+ this.proposer,
+ this.proposal.targets,
+ this.proposal.values,
+ this.proposal.signatures,
+ this.proposal.data,
+ (await time.clockFromReceipt[mode](txPropose)) + votingDelay,
+ (await time.clockFromReceipt[mode](txPropose)) + votingDelay + votingPeriod,
+ this.proposal.description,
+ );
+ });
+
+ it('someone else can propose', async function () {
+ const txPropose = await this.helper.connect(this.voter1).propose();
+
+ await expect(txPropose)
+ .to.emit(this.mock, 'ProposalCreated')
+ .withArgs(
+ this.proposal.id,
+ this.voter1,
+ this.proposal.targets,
+ this.proposal.values,
+ this.proposal.signatures,
+ this.proposal.data,
+ (await time.clockFromReceipt[mode](txPropose)) + votingDelay,
+ (await time.clockFromReceipt[mode](txPropose)) + votingDelay + votingPeriod,
+ this.proposal.description,
+ );
+ });
+ }
+
+ describe('without protection', function () {
+ describe('without suffix', function () {
+ shouldPropose();
+ });
+
+ describe('with different suffix', function () {
+ beforeEach(function () {
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ `#wrong-suffix=${this.proposer}`,
+ );
+ });
+
+ shouldPropose();
+ });
+
+ describe('with proposer suffix but bad address part', function () {
+ beforeEach(function () {
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ `#proposer=0x3C44CdDdB6a900fa2b585dd299e03d12FA429XYZ`, // XYZ are not a valid hex char
+ );
+ });
+
+ shouldPropose();
+ });
+ });
+
+ describe('with protection via proposer suffix', function () {
+ beforeEach(function () {
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ `#proposer=${this.proposer}`,
+ );
+ });
+
+ shouldPropose();
+ });
+ });
+
+ describe('onlyGovernance updates', function () {
+ it('setVotingDelay is protected', async function () {
+ await expect(this.mock.connect(this.owner).setVotingDelay(0n))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('setVotingPeriod is protected', async function () {
+ await expect(this.mock.connect(this.owner).setVotingPeriod(32n))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('setProposalThreshold is protected', async function () {
+ await expect(this.mock.connect(this.owner).setProposalThreshold(1_000_000_000_000_000_000n))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can setVotingDelay through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setVotingDelay', [0n]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute()).to.emit(this.mock, 'VotingDelaySet').withArgs(4n, 0n);
+
+ expect(await this.mock.votingDelay()).to.equal(0n);
+ });
+
+ it('can setVotingPeriod through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setVotingPeriod', [32n]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute()).to.emit(this.mock, 'VotingPeriodSet').withArgs(16n, 32n);
+
+ expect(await this.mock.votingPeriod()).to.equal(32n);
+ });
+
+ it('cannot setVotingPeriod to 0 through governance', async function () {
+ const votingPeriod = 0n;
+
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setVotingPeriod', [votingPeriod]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidVotingPeriod')
+ .withArgs(votingPeriod);
+ });
+
+ it('can setProposalThreshold to 0 through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setProposalThreshold', [1_000_000_000_000_000_000n]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute())
+ .to.emit(this.mock, 'ProposalThresholdSet')
+ .withArgs(0n, 1_000_000_000_000_000_000n);
+
+ expect(await this.mock.proposalThreshold()).to.equal(1_000_000_000_000_000_000n);
+ });
+ });
+
+ describe('safe receive', function () {
+ describe('ERC721', function () {
+ const tokenId = 1n;
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC721', ['Non Fungible Token', 'NFT']);
+ await this.token.$_mint(this.owner, tokenId);
+ });
+
+ it('can receive an ERC721 safeTransfer', async function () {
+ await this.token.connect(this.owner).safeTransferFrom(this.owner, this.mock, tokenId);
+ });
+ });
+
+ describe('ERC1155', function () {
+ const tokenIds = {
+ 1: 1000n,
+ 2: 2000n,
+ 3: 3000n,
+ };
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC1155', ['https://token-cdn-domain/{id}.json']);
+ await this.token.$_mintBatch(this.owner, Object.keys(tokenIds), Object.values(tokenIds), '0x');
+ });
+
+ it('can receive ERC1155 safeTransfer', async function () {
+ await this.token.connect(this.owner).safeTransferFrom(
+ this.owner,
+ this.mock,
+ ...Object.entries(tokenIds)[0], // id + amount
+ '0x',
+ );
+ });
+
+ it('can receive ERC1155 safeBatchTransfer', async function () {
+ await this.token
+ .connect(this.owner)
+ .safeBatchTransferFrom(this.owner, this.mock, Object.keys(tokenIds), Object.values(tokenIds), '0x');
+ });
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/TimelockController.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/TimelockController.test.js
new file mode 100644
index 000000000..08410d460
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/TimelockController.test.js
@@ -0,0 +1,1279 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { GovernorHelper } = require('../helpers/governance');
+const { OperationState } = require('../helpers/enums');
+const time = require('../helpers/time');
+
+const { shouldSupportInterfaces } = require('../utils/introspection/SupportsInterface.behavior');
+
+const salt = '0x025e7b0be353a74631ad648c667493c0e1cd31caa4cc2d3520fdc171ea0cc726'; // a random value
+
+const MINDELAY = time.duration.days(1);
+const DEFAULT_ADMIN_ROLE = ethers.ZeroHash;
+const PROPOSER_ROLE = ethers.id('PROPOSER_ROLE');
+const EXECUTOR_ROLE = ethers.id('EXECUTOR_ROLE');
+const CANCELLER_ROLE = ethers.id('CANCELLER_ROLE');
+
+const getAddress = obj => obj.address ?? obj.target ?? obj;
+
+function genOperation(target, value, data, predecessor, salt) {
+ const id = ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(
+ ['address', 'uint256', 'bytes', 'uint256', 'bytes32'],
+ [getAddress(target), value, data, predecessor, salt],
+ ),
+ );
+ return { id, target, value, data, predecessor, salt };
+}
+
+function genOperationBatch(targets, values, payloads, predecessor, salt) {
+ const id = ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(
+ ['address[]', 'uint256[]', 'bytes[]', 'uint256', 'bytes32'],
+ [targets.map(getAddress), values, payloads, predecessor, salt],
+ ),
+ );
+ return { id, targets, values, payloads, predecessor, salt };
+}
+
+async function fixture() {
+ const [admin, proposer, canceller, executor, other] = await ethers.getSigners();
+
+ const mock = await ethers.deployContract('TimelockController', [MINDELAY, [proposer], [executor], admin]);
+ const callreceivermock = await ethers.deployContract('CallReceiverMock');
+ const implementation2 = await ethers.deployContract('Implementation2');
+
+ expect(await mock.hasRole(CANCELLER_ROLE, proposer)).to.be.true;
+ await mock.connect(admin).revokeRole(CANCELLER_ROLE, proposer);
+ await mock.connect(admin).grantRole(CANCELLER_ROLE, canceller);
+
+ return {
+ admin,
+ proposer,
+ canceller,
+ executor,
+ other,
+ mock,
+ callreceivermock,
+ implementation2,
+ };
+}
+
+describe('TimelockController', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldSupportInterfaces(['ERC1155Receiver']);
+
+ it('initial state', async function () {
+ expect(await this.mock.getMinDelay()).to.equal(MINDELAY);
+
+ expect(await this.mock.DEFAULT_ADMIN_ROLE()).to.equal(DEFAULT_ADMIN_ROLE);
+ expect(await this.mock.PROPOSER_ROLE()).to.equal(PROPOSER_ROLE);
+ expect(await this.mock.EXECUTOR_ROLE()).to.equal(EXECUTOR_ROLE);
+ expect(await this.mock.CANCELLER_ROLE()).to.equal(CANCELLER_ROLE);
+
+ expect(
+ await Promise.all(
+ [PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE].map(role => this.mock.hasRole(role, this.proposer)),
+ ),
+ ).to.deep.equal([true, false, false]);
+
+ expect(
+ await Promise.all(
+ [PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE].map(role => this.mock.hasRole(role, this.canceller)),
+ ),
+ ).to.deep.equal([false, true, false]);
+
+ expect(
+ await Promise.all(
+ [PROPOSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE].map(role => this.mock.hasRole(role, this.executor)),
+ ),
+ ).to.deep.equal([false, false, true]);
+ });
+
+ it('optional admin', async function () {
+ const mock = await ethers.deployContract('TimelockController', [
+ MINDELAY,
+ [this.proposer],
+ [this.executor],
+ ethers.ZeroAddress,
+ ]);
+ expect(await mock.hasRole(DEFAULT_ADMIN_ROLE, this.admin)).to.be.false;
+ expect(await mock.hasRole(DEFAULT_ADMIN_ROLE, mock.target)).to.be.true;
+ });
+
+ describe('methods', function () {
+ describe('operation hashing', function () {
+ it('hashOperation', async function () {
+ this.operation = genOperation(
+ '0x29cebefe301c6ce1bb36b58654fea275e1cacc83',
+ '0xf94fdd6e21da21d2',
+ '0xa3bc5104',
+ '0xba41db3be0a9929145cfe480bd0f1f003689104d275ae912099f925df424ef94',
+ '0x60d9109846ab510ed75c15f979ae366a8a2ace11d34ba9788c13ac296db50e6e',
+ );
+ expect(
+ await this.mock.hashOperation(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ ).to.equal(this.operation.id);
+ });
+
+ it('hashOperationBatch', async function () {
+ this.operation = genOperationBatch(
+ Array(8).fill('0x2d5f21620e56531c1d59c2df9b8e95d129571f71'),
+ Array(8).fill('0x2b993cfce932ccee'),
+ Array(8).fill('0xcf51966b'),
+ '0xce8f45069cc71d25f71ba05062de1a3974f9849b004de64a70998bca9d29c2e7',
+ '0x8952d74c110f72bfe5accdf828c74d53a7dfb71235dfa8a1e8c75d8576b372ff',
+ );
+ expect(
+ await this.mock.hashOperationBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ ).to.equal(this.operation.id);
+ });
+ });
+ describe('simple', function () {
+ describe('schedule', function () {
+ beforeEach(async function () {
+ this.operation = genOperation(
+ '0x31754f590B97fD975Eb86938f18Cc304E264D2F2',
+ 0n,
+ '0x3bf92ccc',
+ ethers.ZeroHash,
+ salt,
+ );
+ });
+
+ it('proposer can schedule', async function () {
+ const tx = await this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+
+ await expect(tx)
+ .to.emit(this.mock, 'CallScheduled')
+ .withArgs(
+ this.operation.id,
+ 0n,
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ MINDELAY,
+ )
+ .to.emit(this.mock, 'CallSalt')
+ .withArgs(this.operation.id, this.operation.salt);
+
+ expect(await this.mock.getTimestamp(this.operation.id)).to.equal(
+ (await time.clockFromReceipt.timestamp(tx)) + MINDELAY,
+ );
+ });
+
+ it('prevent overwriting active operation', async function () {
+ await this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Unset));
+ });
+
+ it('prevent non-proposer from committing', async function () {
+ await expect(
+ this.mock
+ .connect(this.other)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, PROPOSER_ROLE);
+ });
+
+ it('enforce minimum delay', async function () {
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY - 1n,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInsufficientDelay')
+ .withArgs(MINDELAY - 1n, MINDELAY);
+ });
+
+ it('schedule operation with salt zero', async function () {
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ ethers.ZeroHash,
+ MINDELAY,
+ ),
+ ).to.not.emit(this.mock, 'CallSalt');
+ });
+ });
+
+ describe('execute', function () {
+ beforeEach(async function () {
+ this.operation = genOperation(
+ '0xAe22104DCD970750610E6FE15E623468A98b15f7',
+ 0n,
+ '0x13e414de',
+ ethers.ZeroHash,
+ '0xc1059ed2dc130227aa1d1d539ac94c641306905c020436c636e19e3fab56fc7f',
+ );
+ });
+
+ it('revert if operation is not scheduled', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ describe('with scheduled operation', function () {
+ beforeEach(async function () {
+ await this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+ });
+
+ it('revert if execution comes too early 1/2', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ it('revert if execution comes too early 2/2', async function () {
+ // -1 is too tight, test sometime fails
+ await this.mock.getTimestamp(this.operation.id).then(clock => time.increaseTo.timestamp(clock - 5n));
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ describe('on time', function () {
+ beforeEach(async function () {
+ await this.mock.getTimestamp(this.operation.id).then(time.increaseTo.timestamp);
+ });
+
+ it('executor can reveal', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.emit(this.mock, 'CallExecuted')
+ .withArgs(this.operation.id, 0n, this.operation.target, this.operation.value, this.operation.data);
+ });
+
+ it('prevent non-executor from revealing', async function () {
+ await expect(
+ this.mock
+ .connect(this.other)
+ .execute(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, EXECUTOR_ROLE);
+ });
+
+ it('prevents reentrancy execution', async function () {
+ // Create operation
+ const reentrant = await ethers.deployContract('$TimelockReentrant');
+ const reentrantOperation = genOperation(
+ reentrant,
+ 0n,
+ reentrant.interface.encodeFunctionData('reenter'),
+ ethers.ZeroHash,
+ salt,
+ );
+
+ // Schedule so it can be executed
+ await this.mock
+ .connect(this.proposer)
+ .schedule(
+ reentrantOperation.target,
+ reentrantOperation.value,
+ reentrantOperation.data,
+ reentrantOperation.predecessor,
+ reentrantOperation.salt,
+ MINDELAY,
+ );
+
+ // Advance on time to make the operation executable
+ await this.mock.getTimestamp(reentrantOperation.id).then(time.increaseTo.timestamp);
+
+ // Grant executor role to the reentrant contract
+ await this.mock.connect(this.admin).grantRole(EXECUTOR_ROLE, reentrant);
+
+ // Prepare reenter
+ const data = this.mock.interface.encodeFunctionData('execute', [
+ getAddress(reentrantOperation.target),
+ reentrantOperation.value,
+ reentrantOperation.data,
+ reentrantOperation.predecessor,
+ reentrantOperation.salt,
+ ]);
+ await reentrant.enableRentrancy(this.mock, data);
+
+ // Expect to fail
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ reentrantOperation.target,
+ reentrantOperation.value,
+ reentrantOperation.data,
+ reentrantOperation.predecessor,
+ reentrantOperation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(reentrantOperation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+
+ // Disable reentrancy
+ await reentrant.disableReentrancy();
+ const nonReentrantOperation = reentrantOperation; // Not anymore
+
+ // Try again successfully
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ nonReentrantOperation.target,
+ nonReentrantOperation.value,
+ nonReentrantOperation.data,
+ nonReentrantOperation.predecessor,
+ nonReentrantOperation.salt,
+ ),
+ )
+ .to.emit(this.mock, 'CallExecuted')
+ .withArgs(
+ nonReentrantOperation.id,
+ 0n,
+ getAddress(nonReentrantOperation),
+ nonReentrantOperation.value,
+ nonReentrantOperation.data,
+ );
+ });
+ });
+ });
+ });
+ });
+
+ describe('batch', function () {
+ describe('schedule', function () {
+ beforeEach(async function () {
+ this.operation = genOperationBatch(
+ Array(8).fill('0xEd912250835c812D4516BBD80BdaEA1bB63a293C'),
+ Array(8).fill(0n),
+ Array(8).fill('0x2fcb7a88'),
+ ethers.ZeroHash,
+ '0x6cf9d042ade5de78bed9ffd075eb4b2a4f6b1736932c2dc8af517d6e066f51f5',
+ );
+ });
+
+ it('proposer can schedule', async function () {
+ const tx = this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+ for (const i in this.operation.targets) {
+ await expect(tx)
+ .to.emit(this.mock, 'CallScheduled')
+ .withArgs(
+ this.operation.id,
+ i,
+ getAddress(this.operation.targets[i]),
+ this.operation.values[i],
+ this.operation.payloads[i],
+ this.operation.predecessor,
+ MINDELAY,
+ )
+ .to.emit(this.mock, 'CallSalt')
+ .withArgs(this.operation.id, this.operation.salt);
+ }
+
+ expect(await this.mock.getTimestamp(this.operation.id)).to.equal(
+ (await time.clockFromReceipt.timestamp(tx)) + MINDELAY,
+ );
+ });
+
+ it('prevent overwriting active operation', async function () {
+ await this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Unset));
+ });
+
+ it('length of batch parameter must match #1', async function () {
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ [],
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInvalidOperationLength')
+ .withArgs(this.operation.targets.length, this.operation.payloads.length, 0n);
+ });
+
+ it('length of batch parameter must match #1', async function () {
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ [],
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInvalidOperationLength')
+ .withArgs(this.operation.targets.length, 0n, this.operation.payloads.length);
+ });
+
+ it('prevent non-proposer from committing', async function () {
+ await expect(
+ this.mock
+ .connect(this.other)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, PROPOSER_ROLE);
+ });
+
+ it('enforce minimum delay', async function () {
+ await expect(
+ this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY - 1n,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInsufficientDelay')
+ .withArgs(MINDELAY - 1n, MINDELAY);
+ });
+ });
+
+ describe('execute', function () {
+ beforeEach(async function () {
+ this.operation = genOperationBatch(
+ Array(8).fill('0x76E53CcEb05131Ef5248553bEBDb8F70536830b1'),
+ Array(8).fill(0n),
+ Array(8).fill('0x58a60f63'),
+ ethers.ZeroHash,
+ '0x9545eeabc7a7586689191f78a5532443698538e54211b5bd4d7dc0fc0102b5c7',
+ );
+ });
+
+ it('revert if operation is not scheduled', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ describe('with scheduled operation', function () {
+ beforeEach(async function () {
+ await this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+ });
+
+ it('revert if execution comes too early 1/2', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ it('revert if execution comes too early 2/2', async function () {
+ // -1 is to tight, test sometime fails
+ await this.mock.getTimestamp(this.operation.id).then(clock => time.increaseTo.timestamp(clock - 5n));
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.operation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ describe('on time', function () {
+ beforeEach(async function () {
+ await this.mock.getTimestamp(this.operation.id).then(time.increaseTo.timestamp);
+ });
+
+ it('executor can reveal', async function () {
+ const tx = this.mock
+ .connect(this.executor)
+ .executeBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ );
+ for (const i in this.operation.targets) {
+ await expect(tx)
+ .to.emit(this.mock, 'CallExecuted')
+ .withArgs(
+ this.operation.id,
+ i,
+ this.operation.targets[i],
+ this.operation.values[i],
+ this.operation.payloads[i],
+ );
+ }
+ });
+
+ it('prevent non-executor from revealing', async function () {
+ await expect(
+ this.mock
+ .connect(this.other)
+ .executeBatch(
+ this.operation.targets,
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, EXECUTOR_ROLE);
+ });
+
+ it('length mismatch #1', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ [],
+ this.operation.values,
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInvalidOperationLength')
+ .withArgs(0, this.operation.payloads.length, this.operation.values.length);
+ });
+
+ it('length mismatch #2', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ this.operation.targets,
+ [],
+ this.operation.payloads,
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInvalidOperationLength')
+ .withArgs(this.operation.targets.length, this.operation.payloads.length, 0n);
+ });
+
+ it('length mismatch #3', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ this.operation.targets,
+ this.operation.values,
+ [],
+ this.operation.predecessor,
+ this.operation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockInvalidOperationLength')
+ .withArgs(this.operation.targets.length, 0n, this.operation.values.length);
+ });
+
+ it('prevents reentrancy execution', async function () {
+ // Create operation
+ const reentrant = await ethers.deployContract('$TimelockReentrant');
+ const reentrantBatchOperation = genOperationBatch(
+ [reentrant],
+ [0n],
+ [reentrant.interface.encodeFunctionData('reenter')],
+ ethers.ZeroHash,
+ salt,
+ );
+
+ // Schedule so it can be executed
+ await this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ reentrantBatchOperation.targets,
+ reentrantBatchOperation.values,
+ reentrantBatchOperation.payloads,
+ reentrantBatchOperation.predecessor,
+ reentrantBatchOperation.salt,
+ MINDELAY,
+ );
+
+ // Advance on time to make the operation executable
+ await this.mock.getTimestamp(reentrantBatchOperation.id).then(time.increaseTo.timestamp);
+
+ // Grant executor role to the reentrant contract
+ await this.mock.connect(this.admin).grantRole(EXECUTOR_ROLE, reentrant);
+
+ // Prepare reenter
+ const data = this.mock.interface.encodeFunctionData('executeBatch', [
+ reentrantBatchOperation.targets.map(getAddress),
+ reentrantBatchOperation.values,
+ reentrantBatchOperation.payloads,
+ reentrantBatchOperation.predecessor,
+ reentrantBatchOperation.salt,
+ ]);
+ await reentrant.enableRentrancy(this.mock, data);
+
+ // Expect to fail
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ reentrantBatchOperation.targets,
+ reentrantBatchOperation.values,
+ reentrantBatchOperation.payloads,
+ reentrantBatchOperation.predecessor,
+ reentrantBatchOperation.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(reentrantBatchOperation.id, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+
+ // Disable reentrancy
+ await reentrant.disableReentrancy();
+ const nonReentrantBatchOperation = reentrantBatchOperation; // Not anymore
+
+ // Try again successfully
+ const tx = this.mock
+ .connect(this.executor)
+ .executeBatch(
+ nonReentrantBatchOperation.targets,
+ nonReentrantBatchOperation.values,
+ nonReentrantBatchOperation.payloads,
+ nonReentrantBatchOperation.predecessor,
+ nonReentrantBatchOperation.salt,
+ );
+ for (const i in nonReentrantBatchOperation.targets) {
+ await expect(tx)
+ .to.emit(this.mock, 'CallExecuted')
+ .withArgs(
+ nonReentrantBatchOperation.id,
+ i,
+ nonReentrantBatchOperation.targets[i],
+ nonReentrantBatchOperation.values[i],
+ nonReentrantBatchOperation.payloads[i],
+ );
+ }
+ });
+ });
+ });
+
+ it('partial execution', async function () {
+ const operation = genOperationBatch(
+ [this.callreceivermock, this.callreceivermock, this.callreceivermock],
+ [0n, 0n, 0n],
+ [
+ this.callreceivermock.interface.encodeFunctionData('mockFunction'),
+ this.callreceivermock.interface.encodeFunctionData('mockFunctionRevertsNoReason'),
+ this.callreceivermock.interface.encodeFunctionData('mockFunction'),
+ ],
+ ethers.ZeroHash,
+ '0x8ac04aa0d6d66b8812fb41d39638d37af0a9ab11da507afd65c509f8ed079d3e',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .scheduleBatch(
+ operation.targets,
+ operation.values,
+ operation.payloads,
+ operation.predecessor,
+ operation.salt,
+ MINDELAY,
+ );
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .executeBatch(
+ operation.targets,
+ operation.values,
+ operation.payloads,
+ operation.predecessor,
+ operation.salt,
+ ),
+ ).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+ });
+ });
+ });
+
+ describe('cancel', function () {
+ beforeEach(async function () {
+ this.operation = genOperation(
+ '0xC6837c44AA376dbe1d2709F13879E040CAb653ca',
+ 0n,
+ '0x296e58dd',
+ ethers.ZeroHash,
+ '0xa2485763600634800df9fc9646fb2c112cf98649c55f63dd1d9c7d13a64399d9',
+ );
+ await this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation.target,
+ this.operation.value,
+ this.operation.data,
+ this.operation.predecessor,
+ this.operation.salt,
+ MINDELAY,
+ );
+ });
+
+ it('canceller can cancel', async function () {
+ await expect(this.mock.connect(this.canceller).cancel(this.operation.id))
+ .to.emit(this.mock, 'Cancelled')
+ .withArgs(this.operation.id);
+ });
+
+ it('cannot cancel invalid operation', async function () {
+ await expect(this.mock.connect(this.canceller).cancel(ethers.ZeroHash))
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexpectedOperationState')
+ .withArgs(
+ ethers.ZeroHash,
+ GovernorHelper.proposalStatesToBitMap([OperationState.Waiting, OperationState.Ready]),
+ );
+ });
+
+ it('prevent non-canceller from canceling', async function () {
+ await expect(this.mock.connect(this.other).cancel(this.operation.id))
+ .to.be.revertedWithCustomError(this.mock, 'AccessControlUnauthorizedAccount')
+ .withArgs(this.other, CANCELLER_ROLE);
+ });
+ });
+ });
+
+ describe('maintenance', function () {
+ it('prevent unauthorized maintenance', async function () {
+ await expect(this.mock.connect(this.other).updateDelay(0n))
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnauthorizedCaller')
+ .withArgs(this.other);
+ });
+
+ it('timelock scheduled maintenance', async function () {
+ const newDelay = time.duration.hours(6);
+ const operation = genOperation(
+ this.mock,
+ 0n,
+ this.mock.interface.encodeFunctionData('updateDelay', [newDelay]),
+ ethers.ZeroHash,
+ '0xf8e775b2c5f4d66fb5c7fa800f35ef518c262b6014b3c0aee6ea21bff157f108',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt),
+ )
+ .to.emit(this.mock, 'MinDelayChange')
+ .withArgs(MINDELAY, newDelay);
+
+ expect(await this.mock.getMinDelay()).to.equal(newDelay);
+ });
+ });
+
+ describe('dependency', function () {
+ beforeEach(async function () {
+ this.operation1 = genOperation(
+ '0xdE66bD4c97304200A95aE0AadA32d6d01A867E39',
+ 0n,
+ '0x01dc731a',
+ ethers.ZeroHash,
+ '0x64e932133c7677402ead2926f86205e2ca4686aebecf5a8077627092b9bb2feb',
+ );
+ this.operation2 = genOperation(
+ '0x3c7944a3F1ee7fc8c5A5134ba7c79D11c3A1FCa3',
+ 0n,
+ '0x8f531849',
+ this.operation1.id,
+ '0x036e1311cac523f9548e6461e29fb1f8f9196b91910a41711ea22f5de48df07d',
+ );
+ await this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation1.target,
+ this.operation1.value,
+ this.operation1.data,
+ this.operation1.predecessor,
+ this.operation1.salt,
+ MINDELAY,
+ );
+ await this.mock
+ .connect(this.proposer)
+ .schedule(
+ this.operation2.target,
+ this.operation2.value,
+ this.operation2.data,
+ this.operation2.predecessor,
+ this.operation2.salt,
+ MINDELAY,
+ );
+
+ await this.mock.getTimestamp(this.operation2.id).then(time.increaseTo.timestamp);
+ });
+
+ it('cannot execute before dependency', async function () {
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation2.target,
+ this.operation2.value,
+ this.operation2.data,
+ this.operation2.predecessor,
+ this.operation2.salt,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'TimelockUnexecutedPredecessor')
+ .withArgs(this.operation1.id);
+ });
+
+ it('can execute after dependency', async function () {
+ await this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation1.target,
+ this.operation1.value,
+ this.operation1.data,
+ this.operation1.predecessor,
+ this.operation1.salt,
+ );
+ await this.mock
+ .connect(this.executor)
+ .execute(
+ this.operation2.target,
+ this.operation2.value,
+ this.operation2.data,
+ this.operation2.predecessor,
+ this.operation2.salt,
+ );
+ });
+ });
+
+ describe('usage scenario', function () {
+ this.timeout(10000);
+
+ it('call', async function () {
+ const operation = genOperation(
+ this.implementation2,
+ 0n,
+ this.implementation2.interface.encodeFunctionData('setValue', [42n]),
+ ethers.ZeroHash,
+ '0x8043596363daefc89977b25f9d9b4d06c3910959ef0c4d213557a903e1b555e2',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ await this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt);
+
+ expect(await this.implementation2.getValue()).to.equal(42n);
+ });
+
+ it('call reverting', async function () {
+ const operation = genOperation(
+ this.callreceivermock,
+ 0n,
+ this.callreceivermock.interface.encodeFunctionData('mockFunctionRevertsNoReason'),
+ ethers.ZeroHash,
+ '0xb1b1b276fdf1a28d1e00537ea73b04d56639128b08063c1a2f70a52e38cba693',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt),
+ ).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+ });
+
+ it('call throw', async function () {
+ const operation = genOperation(
+ this.callreceivermock,
+ 0n,
+ this.callreceivermock.interface.encodeFunctionData('mockFunctionThrows'),
+ ethers.ZeroHash,
+ '0xe5ca79f295fc8327ee8a765fe19afb58f4a0cbc5053642bfdd7e73bc68e0fc67',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ // Targeted function reverts with a panic code (0x1) + the timelock bubble the panic code
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt),
+ ).to.be.revertedWithPanic(PANIC_CODES.ASSERTION_ERROR);
+ });
+
+ it('call out of gas', async function () {
+ const operation = genOperation(
+ this.callreceivermock,
+ 0n,
+ this.callreceivermock.interface.encodeFunctionData('mockFunctionOutOfGas'),
+ ethers.ZeroHash,
+ '0xf3274ce7c394c5b629d5215723563a744b817e1730cca5587c567099a14578fd',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, {
+ gasLimit: '100000',
+ }),
+ ).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+ });
+
+ it('call payable with eth', async function () {
+ const operation = genOperation(
+ this.callreceivermock,
+ 1,
+ this.callreceivermock.interface.encodeFunctionData('mockFunction'),
+ ethers.ZeroHash,
+ '0x5ab73cd33477dcd36c1e05e28362719d0ed59a7b9ff14939de63a43073dc1f44',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.callreceivermock)).to.equal(0n);
+
+ await this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, {
+ value: 1,
+ });
+
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.callreceivermock)).to.equal(1n);
+ });
+
+ it('call nonpayable with eth', async function () {
+ const operation = genOperation(
+ this.callreceivermock,
+ 1,
+ this.callreceivermock.interface.encodeFunctionData('mockFunctionNonPayable'),
+ ethers.ZeroHash,
+ '0xb78edbd920c7867f187e5aa6294ae5a656cfbf0dea1ccdca3751b740d0f2bdf8',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.callreceivermock)).to.equal(0n);
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt),
+ ).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.callreceivermock)).to.equal(0n);
+ });
+
+ it('call reverting with eth', async function () {
+ const operation = genOperation(
+ this.callreceivermock,
+ 1,
+ this.callreceivermock.interface.encodeFunctionData('mockFunctionRevertsNoReason'),
+ ethers.ZeroHash,
+ '0xdedb4563ef0095db01d81d3f2decf57cf83e4a72aa792af14c43a792b56f4de6',
+ );
+
+ await this.mock
+ .connect(this.proposer)
+ .schedule(operation.target, operation.value, operation.data, operation.predecessor, operation.salt, MINDELAY);
+
+ await this.mock.getTimestamp(operation.id).then(time.increaseTo.timestamp);
+
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.callreceivermock)).to.equal(0n);
+
+ await expect(
+ this.mock
+ .connect(this.executor)
+ .execute(operation.target, operation.value, operation.data, operation.predecessor, operation.salt),
+ ).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.callreceivermock)).to.equal(0n);
+ });
+ });
+
+ describe('safe receive', function () {
+ describe('ERC721', function () {
+ const tokenId = 1n;
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC721', ['Non Fungible Token', 'NFT']);
+ await this.token.$_mint(this.other, tokenId);
+ });
+
+ it('can receive an ERC721 safeTransfer', async function () {
+ await this.token.connect(this.other).safeTransferFrom(this.other, this.mock, tokenId);
+ });
+ });
+
+ describe('ERC1155', function () {
+ const tokenIds = {
+ 1: 1000n,
+ 2: 2000n,
+ 3: 3000n,
+ };
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC1155', ['https://token-cdn-domain/{id}.json']);
+ await this.token.$_mintBatch(this.other, Object.keys(tokenIds), Object.values(tokenIds), '0x');
+ });
+
+ it('can receive ERC1155 safeTransfer', async function () {
+ await this.token.connect(this.other).safeTransferFrom(
+ this.other,
+ this.mock,
+ ...Object.entries(tokenIds)[0n], // id + amount
+ '0x',
+ );
+ });
+
+ it('can receive ERC1155 safeBatchTransfer', async function () {
+ await this.token
+ .connect(this.other)
+ .safeBatchTransferFrom(this.other, this.mock, Object.keys(tokenIds), Object.values(tokenIds), '0x');
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingFractional.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingFractional.test.js
new file mode 100644
index 000000000..393dbad79
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingFractional.test.js
@@ -0,0 +1,248 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { VoteType } = require('../../helpers/enums');
+const { zip } = require('../../helpers/iterate');
+const { sum } = require('../../helpers/math');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+describe('GovernorCountingFractional', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, proposer, voter1, voter2, voter3, voter4, other] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorFractionalMock', [
+ name, // name
+ votingDelay, // initialVotingDelay
+ votingPeriod, // initialVotingPeriod
+ 0n, // initialProposalThreshold
+ token, // tokenAddress
+ 10n, // quorumNumeratorValue
+ ]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { owner, proposer, voter1, voter2, voter3, voter4, other, receiver, token, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // default proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ value,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ },
+ ],
+ '',
+ );
+ });
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.COUNTING_MODE()).to.equal(
+ 'support=bravo,fractional&quorum=for,abstain¶ms=fractional',
+ );
+ });
+
+ it('nominal is unaffected', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For, reason: 'This is nice' });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.true;
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.receiver)).to.equal(value);
+ });
+
+ describe('voting with a fraction of the weight', function () {
+ it('twice', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([0n, 0n, 0n]);
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.equal(false);
+ expect(await this.mock.usedVotes(this.proposal.id, this.voter2)).to.equal(0n);
+
+ const steps = [
+ ['0', '2', '1'],
+ ['1', '0', '1'],
+ ].map(votes => votes.map(vote => ethers.parseEther(vote)));
+
+ for (const votes of steps) {
+ const params = ethers.solidityPacked(['uint128', 'uint128', 'uint128'], votes);
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.Parameters,
+ reason: 'no particular reason',
+ params,
+ }),
+ )
+ .to.emit(this.mock, 'VoteCastWithParams')
+ .withArgs(
+ this.voter2,
+ this.proposal.id,
+ VoteType.Parameters,
+ sum(...votes),
+ 'no particular reason',
+ params,
+ );
+ }
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal(zip(...steps).map(v => sum(...v)));
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.equal(true);
+ expect(await this.mock.usedVotes(this.proposal.id, this.voter2)).to.equal(sum(...[].concat(...steps)));
+ });
+
+ it('fractional then nominal', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([0n, 0n, 0n]);
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.equal(false);
+ expect(await this.mock.usedVotes(this.proposal.id, this.voter2)).to.equal(0n);
+
+ const weight = ethers.parseEther('7');
+ const fractional = ['1', '2', '1'].map(ethers.parseEther);
+
+ const params = ethers.solidityPacked(['uint128', 'uint128', 'uint128'], fractional);
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.Parameters,
+ reason: 'no particular reason',
+ params,
+ }),
+ )
+ .to.emit(this.mock, 'VoteCastWithParams')
+ .withArgs(
+ this.voter2,
+ this.proposal.id,
+ VoteType.Parameters,
+ sum(...fractional),
+ 'no particular reason',
+ params,
+ );
+
+ await expect(this.helper.connect(this.voter2).vote({ support: VoteType.Against }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter2, this.proposal.id, VoteType.Against, weight - sum(...fractional), '');
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([
+ weight - sum(...fractional.slice(1)),
+ ...fractional.slice(1),
+ ]);
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.equal(true);
+ expect(await this.mock.usedVotes(this.proposal.id, this.voter2)).to.equal(weight);
+ });
+
+ it('revert if params spend more than available', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ const weight = ethers.parseEther('7');
+ const fractional = ['0', '1000', '0'].map(ethers.parseEther);
+
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.Parameters,
+ reason: 'no particular reason',
+ params: ethers.solidityPacked(['uint128', 'uint128', 'uint128'], fractional),
+ }),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'GovernorExceedRemainingWeight')
+ .withArgs(this.voter2, sum(...fractional), weight);
+ });
+
+ it('revert if no weight remaining', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.Parameters,
+ reason: 'no particular reason',
+ params: ethers.solidityPacked(['uint128', 'uint128', 'uint128'], [0n, 1n, 0n]),
+ }),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyCastVote')
+ .withArgs(this.voter2);
+ });
+
+ it('revert if params are not properly formatted #1', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.Parameters,
+ reason: 'no particular reason',
+ params: ethers.solidityPacked(['uint128', 'uint128'], [0n, 1n]),
+ }),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorInvalidVoteParams');
+ });
+
+ it('revert if params are not properly formatted #2', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.Against,
+ reason: 'no particular reason',
+ params: ethers.solidityPacked(['uint128', 'uint128', 'uint128'], [0n, 1n, 0n]),
+ }),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorInvalidVoteParams');
+ });
+
+ it('revert if vote type is invalid', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ await expect(this.helper.connect(this.voter2).vote({ support: 128n })).to.be.revertedWithCustomError(
+ this.mock,
+ 'GovernorInvalidVoteType',
+ );
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingOverridable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingOverridable.test.js
new file mode 100644
index 000000000..32ee47439
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorCountingOverridable.test.js
@@ -0,0 +1,346 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { getDomain, OverrideBallot } = require('../../helpers/eip712');
+const { VoteType } = require('../../helpers/enums');
+
+const TOKENS = [
+ { Token: '$ERC20VotesExtendedMock', mode: 'blocknumber' },
+ { Token: '$ERC20VotesExtendedTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'Override Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+const signBallot = account => (contract, message) =>
+ getDomain(contract).then(domain => account.signTypedData(domain, { OverrideBallot }, message));
+
+describe('GovernorCountingOverridable', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, proposer, voter1, voter2, voter3, voter4, other] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, tokenName, version]);
+ const mock = await ethers.deployContract('$GovernorCountingOverridableMock', [
+ name, // name
+ votingDelay, // initialVotingDelay
+ votingPeriod, // initialVotingPeriod
+ 0n, // initialProposalThreshold
+ token, // tokenAddress
+ 10n, // quorumNumeratorValue
+ ]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { owner, proposer, voter1, voter2, voter3, voter4, other, receiver, token, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // default proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ value,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ },
+ ],
+ '',
+ );
+ });
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.COUNTING_MODE()).to.equal('support=bravo,override&quorum=for,abstain&overridable=true');
+ });
+
+ it('nominal is unaffected', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For, reason: 'This is nice' });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.true;
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.receiver)).to.equal(value);
+ });
+
+ describe('cast override vote', async function () {
+ beforeEach(async function () {
+ // user 1 -(delegate 10 tokens)-> user 2
+ // user 2 -(delegate 7 tokens)-> user 2
+ // user 3 -(delegate 5 tokens)-> user 1
+ // user 4 -(delegate 2 tokens)-> user 2
+ await this.token.connect(this.voter1).delegate(this.voter2);
+ await this.token.connect(this.voter3).delegate(this.voter1);
+ await this.token.connect(this.voter4).delegate(this.voter2);
+ await mine();
+
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ });
+
+ it('override after delegate vote', async function () {
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter2)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter3)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter4)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter2)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter3)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter4)).to.be.false;
+
+ // user 2 votes
+
+ await expect(this.helper.connect(this.voter2).vote({ support: VoteType.For }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter2, this.helper.id, VoteType.For, ethers.parseEther('19'), ''); // 10 + 7 + 2
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [0, 19, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter2)).to.be.true;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter2)).to.be.false;
+
+ // user 1 overrides after user 2 votes
+
+ const reason = "disagree with user 2's decision";
+ await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Against, reason))
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('10'), reason)
+ .to.emit(this.mock, 'VoteReduced')
+ .withArgs(this.voter2, this.helper.id, VoteType.For, ethers.parseEther('10'));
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 9, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.true;
+ });
+
+ it('override before delegate vote', async function () {
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter2)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter3)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter4)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter2)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter3)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter4)).to.be.false;
+
+ // user 1 overrides before user 2 votes
+
+ const reason = 'voter 2 is not voting';
+ await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Against, reason))
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('10'), reason)
+ .to.not.emit(this.mock, 'VoteReduced');
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 0, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.true;
+
+ // user 2 votes
+
+ await expect(this.helper.connect(this.voter2).vote({ support: VoteType.For }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter2, this.helper.id, VoteType.For, ethers.parseEther('9'), ''); // 7 + 2
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 9, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter2)).to.be.true;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter2)).to.be.false;
+ });
+
+ it('override before and after delegate vote', async function () {
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter2)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter3)).to.be.false;
+ expect(await this.mock.hasVoted(this.helper.id, this.voter4)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter2)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter3)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter4)).to.be.false;
+
+ // user 1 overrides before user 2 votes
+
+ const reason = 'voter 2 is not voting';
+ await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Against, reason))
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('10'), reason)
+ .to.not.emit(this.mock, 'VoteReduced');
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 0, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.true;
+
+ // user 2 votes
+
+ await expect(this.helper.connect(this.voter2).vote({ support: VoteType.For }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter2, this.helper.id, VoteType.For, ethers.parseEther('9'), ''); // 7 + 2
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 9, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter2)).to.be.true;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter2)).to.be.false;
+
+ // User 4 overrides after user 2 votes
+
+ const reason2 = "disagree with user 2's decision";
+ await expect(this.mock.connect(this.voter4).castOverrideVote(this.helper.id, VoteType.Abstain, reason2))
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter4, this.helper.id, VoteType.Abstain, ethers.parseEther('2'), reason2)
+ .to.emit(this.mock, 'VoteReduced')
+ .withArgs(this.voter2, this.helper.id, VoteType.For, ethers.parseEther('2'));
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 7, 2].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter4)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter4)).to.be.true;
+ });
+
+ it('vote (with delegated balance) and override (with self balance) are independent', async function () {
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [0, 0, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.false;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.false;
+
+ // user 1 votes with delegated weight from user 3
+ await expect(this.mock.connect(this.voter1).castVote(this.helper.id, VoteType.For))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.For, ethers.parseEther('5'), '');
+
+ // user 1 cast an override vote with its own balance (delegated to user 2)
+ await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Against, ''))
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('10'), '');
+
+ expect(await this.mock.proposalVotes(this.helper.id)).to.deep.eq(
+ [10, 5, 0].map(x => ethers.parseEther(x.toString())),
+ );
+ expect(await this.mock.hasVoted(this.helper.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVotedOverride(this.helper.id, this.voter1)).to.be.true;
+ });
+
+ it('can not override vote twice', async function () {
+ await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Against, ''))
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('10'), '');
+ await expect(this.mock.connect(this.voter1).castOverrideVote(this.helper.id, VoteType.Abstain, ''))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyOverridenVote')
+ .withArgs(this.voter1.address);
+ });
+
+ it('can not vote twice', async function () {
+ await expect(this.mock.connect(this.voter1).castVote(this.helper.id, VoteType.Against))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.Against, ethers.parseEther('5'), '');
+ await expect(this.mock.connect(this.voter1).castVote(this.helper.id, VoteType.Abstain))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyCastVote')
+ .withArgs(this.voter1.address);
+ });
+
+ describe('invalid vote type', function () {
+ it('override vote', async function () {
+ await expect(
+ this.mock.connect(this.voter1).castOverrideVote(this.helper.id, 3, ''),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorInvalidVoteType');
+ });
+
+ it('traditional vote', async function () {
+ await expect(this.mock.connect(this.voter1).castVote(this.helper.id, 3)).to.be.revertedWithCustomError(
+ this.mock,
+ 'GovernorInvalidVoteType',
+ );
+ });
+ });
+
+ describe('by signature', function () {
+ it('EOA signature', async function () {
+ const nonce = await this.mock.nonces(this.voter1);
+
+ await expect(
+ this.helper.overrideVote({
+ support: VoteType.For,
+ voter: this.voter1.address,
+ nonce,
+ signature: signBallot(this.voter1),
+ }),
+ )
+ .to.emit(this.mock, 'OverrideVoteCast')
+ .withArgs(this.voter1, this.helper.id, VoteType.For, ethers.parseEther('10'), '');
+
+ expect(await this.mock.hasVotedOverride(this.proposal.id, this.voter1)).to.be.true;
+ });
+
+ it('revert if signature does not match signer', async function () {
+ const nonce = await this.mock.nonces(this.voter1);
+
+ const voteParams = {
+ support: VoteType.For,
+ voter: this.voter2.address,
+ nonce,
+ signature: signBallot(this.voter1),
+ };
+
+ await expect(this.helper.overrideVote(voteParams))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSignature')
+ .withArgs(voteParams.voter);
+ });
+
+ it('revert if vote nonce is incorrect', async function () {
+ const nonce = await this.mock.nonces(this.voter1);
+
+ const voteParams = {
+ support: VoteType.For,
+ voter: this.voter1.address,
+ nonce: nonce + 1n,
+ signature: signBallot(this.voter1),
+ };
+
+ await expect(this.helper.overrideVote(voteParams))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSignature')
+ .withArgs(voteParams.voter);
+ });
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorERC721.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorERC721.test.js
new file mode 100644
index 000000000..1ae5508d7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorERC721.test.js
@@ -0,0 +1,131 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { VoteType } = require('../../helpers/enums');
+
+const TOKENS = [
+ { Token: '$ERC721Votes', mode: 'blocknumber' },
+ { Token: '$ERC721VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockNFToken';
+const tokenSymbol = 'MTKN';
+const NFT0 = 0n;
+const NFT1 = 1n;
+const NFT2 = 2n;
+const NFT3 = 3n;
+const NFT4 = 4n;
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+describe('GovernorERC721', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, voter1, voter2, voter3, voter4] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorMock', [
+ name, // name
+ votingDelay, // initialVotingDelay
+ votingPeriod, // initialVotingPeriod
+ 0n, // initialProposalThreshold
+ token, // tokenAddress
+ 10n, // quorumNumeratorValue
+ ]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await Promise.all([NFT0, NFT1, NFT2, NFT3, NFT4].map(tokenId => token.$_mint(owner, tokenId)));
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, tokenId: NFT0 });
+ await helper.connect(owner).delegate({ token, to: voter2, tokenId: NFT1 });
+ await helper.connect(owner).delegate({ token, to: voter2, tokenId: NFT2 });
+ await helper.connect(owner).delegate({ token, to: voter3, tokenId: NFT3 });
+ await helper.connect(owner).delegate({ token, to: voter4, tokenId: NFT4 });
+
+ return {
+ owner,
+ voter1,
+ voter2,
+ voter3,
+ voter4,
+ receiver,
+ token,
+ mock,
+ helper,
+ };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ // initiate fresh proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ '',
+ );
+ });
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0n)).to.equal(0n);
+
+ expect(await this.token.getVotes(this.voter1)).to.equal(1n); // NFT0
+ expect(await this.token.getVotes(this.voter2)).to.equal(2n); // NFT1 & NFT2
+ expect(await this.token.getVotes(this.voter3)).to.equal(1n); // NFT3
+ expect(await this.token.getVotes(this.voter4)).to.equal(1n); // NFT4
+ });
+
+ it('voting with ERC721 token', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+
+ await expect(this.helper.connect(this.voter1).vote({ support: VoteType.For }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter1, this.proposal.id, VoteType.For, 1n, '');
+
+ await expect(this.helper.connect(this.voter2).vote({ support: VoteType.For }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter2, this.proposal.id, VoteType.For, 2n, '');
+
+ await expect(this.helper.connect(this.voter3).vote({ support: VoteType.Against }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter3, this.proposal.id, VoteType.Against, 1n, '');
+
+ await expect(this.helper.connect(this.voter4).vote({ support: VoteType.Abstain }))
+ .to.emit(this.mock, 'VoteCast')
+ .withArgs(this.voter4, this.proposal.id, VoteType.Abstain, 1n, '');
+
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter3)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter4)).to.be.true;
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([
+ 1n, // againstVotes
+ 3n, // forVotes
+ 1n, // abstainVotes
+ ]);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorPreventLateQuorum.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorPreventLateQuorum.test.js
new file mode 100644
index 000000000..aac0e6898
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorPreventLateQuorum.test.js
@@ -0,0 +1,185 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { ProposalState, VoteType } = require('../../helpers/enums');
+const time = require('../../helpers/time');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const lateQuorumVoteExtension = 8n;
+const quorum = ethers.parseEther('1');
+const value = ethers.parseEther('1');
+
+describe('GovernorPreventLateQuorum', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, proposer, voter1, voter2, voter3, voter4] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorPreventLateQuorumMock', [
+ name, // name
+ votingDelay, // initialVotingDelay
+ votingPeriod, // initialVotingPeriod
+ 0n, // initialProposalThreshold
+ token, // tokenAddress
+ lateQuorumVoteExtension,
+ quorum,
+ ]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { owner, proposer, voter1, voter2, voter3, voter4, receiver, token, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ // initiate fresh proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ '',
+ );
+ });
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0)).to.equal(quorum);
+ expect(await this.mock.lateQuorumVoteExtension()).to.equal(lateQuorumVoteExtension);
+ });
+
+ it('nominal workflow unaffected', async function () {
+ const txPropose = await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter3)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter4)).to.be.true;
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([
+ ethers.parseEther('5'), // againstVotes
+ ethers.parseEther('17'), // forVotes
+ ethers.parseEther('2'), // abstainVotes
+ ]);
+
+ const voteStart = (await time.clockFromReceipt[mode](txPropose)) + votingDelay;
+ const voteEnd = (await time.clockFromReceipt[mode](txPropose)) + votingDelay + votingPeriod;
+ expect(await this.mock.proposalSnapshot(this.proposal.id)).to.equal(voteStart);
+ expect(await this.mock.proposalDeadline(this.proposal.id)).to.equal(voteEnd);
+
+ await expect(txPropose)
+ .to.emit(this.mock, 'ProposalCreated')
+ .withArgs(
+ this.proposal.id,
+ this.proposer,
+ this.proposal.targets,
+ this.proposal.values,
+ this.proposal.signatures,
+ this.proposal.data,
+ voteStart,
+ voteEnd,
+ this.proposal.description,
+ );
+ });
+
+ it('Delay is extended to prevent last minute take-over', async function () {
+ const txPropose = await this.helper.connect(this.proposer).propose();
+
+ // compute original schedule
+ const snapshotTimepoint = (await time.clockFromReceipt[mode](txPropose)) + votingDelay;
+ const deadlineTimepoint = (await time.clockFromReceipt[mode](txPropose)) + votingDelay + votingPeriod;
+ expect(await this.mock.proposalSnapshot(this.proposal.id)).to.equal(snapshotTimepoint);
+ expect(await this.mock.proposalDeadline(this.proposal.id)).to.equal(deadlineTimepoint);
+ // wait for the last minute to vote
+ await this.helper.waitForDeadline(-1n);
+ const txVote = await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+
+ // cannot execute yet
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Active);
+
+ // compute new extended schedule
+ const extendedDeadline = (await time.clockFromReceipt[mode](txVote)) + lateQuorumVoteExtension;
+ expect(await this.mock.proposalSnapshot(this.proposal.id)).to.equal(snapshotTimepoint);
+ expect(await this.mock.proposalDeadline(this.proposal.id)).to.equal(extendedDeadline);
+
+ // still possible to vote
+ await this.helper.connect(this.voter1).vote({ support: VoteType.Against });
+
+ await this.helper.waitForDeadline();
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Active);
+ await this.helper.waitForDeadline(1n);
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Defeated);
+
+ // check extension event
+ await expect(txVote).to.emit(this.mock, 'ProposalExtended').withArgs(this.proposal.id, extendedDeadline);
+ });
+
+ describe('onlyGovernance updates', function () {
+ it('setLateQuorumVoteExtension is protected', async function () {
+ await expect(this.mock.connect(this.owner).setLateQuorumVoteExtension(0n))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can setLateQuorumVoteExtension through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setLateQuorumVoteExtension', [0n]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute())
+ .to.emit(this.mock, 'LateQuorumVoteExtensionSet')
+ .withArgs(lateQuorumVoteExtension, 0n);
+
+ expect(await this.mock.lateQuorumVoteExtension()).to.equal(0n);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorStorage.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorStorage.test.js
new file mode 100644
index 000000000..ef56fa53e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorStorage.test.js
@@ -0,0 +1,155 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { GovernorHelper, timelockSalt } = require('../../helpers/governance');
+const { VoteType } = require('../../helpers/enums');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const DEFAULT_ADMIN_ROLE = ethers.ZeroHash;
+const PROPOSER_ROLE = ethers.id('PROPOSER_ROLE');
+const EXECUTOR_ROLE = ethers.id('EXECUTOR_ROLE');
+const CANCELLER_ROLE = ethers.id('CANCELLER_ROLE');
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+const delay = 3600n;
+
+describe('GovernorStorage', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [deployer, owner, proposer, voter1, voter2, voter3, voter4] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const timelock = await ethers.deployContract('TimelockController', [delay, [], [], deployer]);
+ const mock = await ethers.deployContract('$GovernorStorageMock', [
+ name,
+ votingDelay,
+ votingPeriod,
+ 0n,
+ timelock,
+ token,
+ 0n,
+ ]);
+
+ await owner.sendTransaction({ to: timelock, value });
+ await token.$_mint(owner, tokenSupply);
+ await timelock.grantRole(PROPOSER_ROLE, mock);
+ await timelock.grantRole(PROPOSER_ROLE, owner);
+ await timelock.grantRole(CANCELLER_ROLE, mock);
+ await timelock.grantRole(CANCELLER_ROLE, owner);
+ await timelock.grantRole(EXECUTOR_ROLE, ethers.ZeroAddress);
+ await timelock.revokeRole(DEFAULT_ADMIN_ROLE, deployer);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { deployer, owner, proposer, voter1, voter2, voter3, voter4, receiver, token, timelock, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ // initiate fresh proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ value,
+ },
+ ],
+ '',
+ );
+ this.proposal.timelockid = await this.timelock.hashOperationBatch(
+ ...this.proposal.shortProposal.slice(0, 3),
+ ethers.ZeroHash,
+ timelockSalt(this.mock.target, this.proposal.shortProposal[3]),
+ );
+ });
+
+ describe('proposal indexing', function () {
+ it('before propose', async function () {
+ expect(await this.mock.proposalCount()).to.equal(0n);
+
+ await expect(this.mock.proposalDetailsAt(0n)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+
+ await expect(this.mock.proposalDetails(this.proposal.id))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNonexistentProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('after propose', async function () {
+ await this.helper.propose();
+
+ expect(await this.mock.proposalCount()).to.equal(1n);
+
+ expect(await this.mock.proposalDetailsAt(0n)).to.deep.equal([
+ this.proposal.id,
+ this.proposal.targets,
+ this.proposal.values,
+ this.proposal.data,
+ this.proposal.descriptionHash,
+ ]);
+
+ expect(await this.mock.proposalDetails(this.proposal.id)).to.deep.equal([
+ this.proposal.targets,
+ this.proposal.values,
+ this.proposal.data,
+ this.proposal.descriptionHash,
+ ]);
+ });
+ });
+
+ it('queue and execute by id', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+
+ await expect(this.mock.queue(this.proposal.id))
+ .to.emit(this.mock, 'ProposalQueued')
+ .withArgs(this.proposal.id, anyValue)
+ .to.emit(this.timelock, 'CallScheduled')
+ .withArgs(this.proposal.timelockid, ...Array(6).fill(anyValue))
+ .to.emit(this.timelock, 'CallSalt')
+ .withArgs(this.proposal.timelockid, anyValue);
+
+ await this.helper.waitForEta();
+
+ await expect(this.mock.execute(this.proposal.id))
+ .to.emit(this.mock, 'ProposalExecuted')
+ .withArgs(this.proposal.id)
+ .to.emit(this.timelock, 'CallExecuted')
+ .withArgs(this.proposal.timelockid, ...Array(4).fill(anyValue))
+ .to.emit(this.receiver, 'MockFunctionCalled');
+ });
+
+ it('cancel by id', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await expect(this.mock.connect(this.proposer).cancel(this.proposal.id))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockAccess.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockAccess.test.js
new file mode 100644
index 000000000..c3d3b3268
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockAccess.test.js
@@ -0,0 +1,864 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { hashOperation } = require('../../helpers/access-manager');
+const { max } = require('../../helpers/math');
+const { selector } = require('../../helpers/methods');
+const { ProposalState, VoteType } = require('../../helpers/enums');
+const time = require('../../helpers/time');
+
+function prepareOperation({ sender, target, value = 0n, data = '0x' }) {
+ return {
+ id: hashOperation(sender, target, data),
+ operation: { target, value, data },
+ selector: data.slice(0, 10).padEnd(10, '0'),
+ };
+}
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+describe('GovernorTimelockAccess', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [admin, voter1, voter2, voter3, voter4, other] = await ethers.getSigners();
+
+ const manager = await ethers.deployContract('$AccessManager', [admin]);
+ const receiver = await ethers.deployContract('$AccessManagedTarget', [manager]);
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorTimelockAccessMock', [
+ name,
+ votingDelay,
+ votingPeriod,
+ 0n,
+ manager,
+ 0n,
+ token,
+ 0n,
+ ]);
+
+ await admin.sendTransaction({ to: mock, value });
+ await token.$_mint(admin, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(admin).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(admin).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(admin).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(admin).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { admin, voter1, voter2, voter3, voter4, other, manager, receiver, token, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // restricted proposal
+ this.restricted = prepareOperation({
+ sender: this.mock.target,
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('fnRestricted'),
+ });
+
+ this.unrestricted = prepareOperation({
+ sender: this.mock.target,
+ target: this.receiver.target,
+ data: this.receiver.interface.encodeFunctionData('fnUnrestricted'),
+ });
+
+ this.fallback = prepareOperation({
+ sender: this.mock.target,
+ target: this.receiver.target,
+ data: '0x1234',
+ });
+ });
+
+ it('accepts ether transfers', async function () {
+ await this.admin.sendTransaction({ to: this.mock, value: 1n });
+ });
+
+ it('post deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0n)).to.equal(0n);
+
+ expect(await this.mock.accessManager()).to.equal(this.manager);
+ });
+
+ it('sets base delay (seconds)', async function () {
+ const baseDelay = time.duration.hours(10n);
+
+ // Only through governance
+ await expect(this.mock.connect(this.voter1).setBaseDelaySeconds(baseDelay))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.voter1);
+
+ this.proposal = await this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setBaseDelaySeconds', [baseDelay]),
+ },
+ ],
+ 'descr',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute()).to.emit(this.mock, 'BaseDelaySet').withArgs(0n, baseDelay);
+
+ expect(await this.mock.baseDelaySeconds()).to.equal(baseDelay);
+ });
+
+ it('sets access manager ignored', async function () {
+ const selectors = ['0x12345678', '0x87654321', '0xabcdef01'];
+
+ // Only through governance
+ await expect(this.mock.connect(this.voter1).setAccessManagerIgnored(this.other, selectors, true))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.voter1);
+
+ // Ignore
+ await this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setAccessManagerIgnored', [
+ this.other.address,
+ selectors,
+ true,
+ ]),
+ },
+ ],
+ 'descr',
+ );
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ const ignoreReceipt = this.helper.execute();
+ for (const selector of selectors) {
+ await expect(ignoreReceipt)
+ .to.emit(this.mock, 'AccessManagerIgnoredSet')
+ .withArgs(this.other, selector, true);
+ expect(await this.mock.isAccessManagerIgnored(this.other, selector)).to.be.true;
+ }
+
+ // Unignore
+ await this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setAccessManagerIgnored', [
+ this.other.address,
+ selectors,
+ false,
+ ]),
+ },
+ ],
+ 'descr',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ const unignoreReceipt = this.helper.execute();
+ for (const selector of selectors) {
+ await expect(unignoreReceipt)
+ .to.emit(this.mock, 'AccessManagerIgnoredSet')
+ .withArgs(this.other, selector, false);
+ expect(await this.mock.isAccessManagerIgnored(this.other, selector)).to.be.false;
+ }
+ });
+
+ it('sets access manager ignored when target is the governor', async function () {
+ const selectors = ['0x12345678', '0x87654321', '0xabcdef01'];
+
+ await this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('setAccessManagerIgnored', [
+ this.mock.target,
+ selectors,
+ true,
+ ]),
+ },
+ ],
+ 'descr',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ const tx = this.helper.execute();
+ for (const selector of selectors) {
+ await expect(tx).to.emit(this.mock, 'AccessManagerIgnoredSet').withArgs(this.mock, selector, true);
+ expect(await this.mock.isAccessManagerIgnored(this.mock, selector)).to.be.true;
+ }
+ });
+
+ it('does not need to queue proposals with no delay', async function () {
+ const roleId = 1n;
+ const executionDelay = 0n;
+ const baseDelay = 0n;
+
+ // Set execution delay
+ await this.manager.connect(this.admin).setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ await this.helper.setProposal([this.restricted.operation], 'descr');
+ await this.helper.propose();
+ expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.false;
+ });
+
+ it('needs to queue proposals with any delay', async function () {
+ const roleId = 1n;
+ const delays = [
+ [time.duration.hours(1n), time.duration.hours(2n)],
+ [time.duration.hours(2n), time.duration.hours(1n)],
+ ];
+
+ for (const [executionDelay, baseDelay] of delays) {
+ // Set execution delay
+ await this.manager
+ .connect(this.admin)
+ .setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ await this.helper.setProposal(
+ [this.restricted.operation],
+ `executionDelay=${executionDelay.toString()}}baseDelay=${baseDelay.toString()}}`,
+ );
+ await this.helper.propose();
+ expect(await this.mock.proposalNeedsQueuing(this.helper.currentProposal.id)).to.be.true;
+ }
+ });
+
+ describe('execution plan', function () {
+ it('returns plan for delayed operations', async function () {
+ const roleId = 1n;
+ const delays = [
+ [time.duration.hours(1n), time.duration.hours(2n)],
+ [time.duration.hours(2n), time.duration.hours(1n)],
+ ];
+
+ for (const [executionDelay, baseDelay] of delays) {
+ // Set execution delay
+ await this.manager
+ .connect(this.admin)
+ .setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ this.proposal = await this.helper.setProposal(
+ [this.restricted.operation],
+ `executionDelay=${executionDelay.toString()}}baseDelay=${baseDelay.toString()}}`,
+ );
+ await this.helper.propose();
+
+ expect(await this.mock.proposalExecutionPlan(this.proposal.id)).to.deep.equal([
+ max(baseDelay, executionDelay),
+ [true],
+ [true],
+ ]);
+ }
+ });
+
+ it('returns plan for not delayed operations', async function () {
+ const roleId = 1n;
+ const executionDelay = 0n;
+ const baseDelay = 0n;
+
+ // Set execution delay
+ await this.manager
+ .connect(this.admin)
+ .setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ this.proposal = await this.helper.setProposal([this.restricted.operation], `descr`);
+ await this.helper.propose();
+
+ expect(await this.mock.proposalExecutionPlan(this.proposal.id)).to.deep.equal([0n, [true], [false]]);
+ });
+
+ it('returns plan for an operation ignoring the manager', async function () {
+ await this.mock.$_setAccessManagerIgnored(this.receiver, this.restricted.selector, true);
+
+ const roleId = 1n;
+ const delays = [
+ [time.duration.hours(1n), time.duration.hours(2n)],
+ [time.duration.hours(2n), time.duration.hours(1n)],
+ ];
+
+ for (const [executionDelay, baseDelay] of delays) {
+ // Set execution delay
+ await this.manager
+ .connect(this.admin)
+ .setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ this.proposal = await this.helper.setProposal(
+ [this.restricted.operation],
+ `executionDelay=${executionDelay.toString()}}baseDelay=${baseDelay.toString()}}`,
+ );
+ await this.helper.propose();
+
+ expect(await this.mock.proposalExecutionPlan(this.proposal.id)).to.deep.equal([
+ baseDelay,
+ [false],
+ [false],
+ ]);
+ }
+ });
+ });
+
+ describe('base delay only', function () {
+ for (const [delay, queue] of [
+ [0, true],
+ [0, false],
+ [1000, true],
+ ]) {
+ it(`delay ${delay}, ${queue ? 'with' : 'without'} queuing`, async function () {
+ await this.mock.$_setBaseDelaySeconds(delay);
+
+ this.proposal = await this.helper.setProposal([this.unrestricted.operation], 'descr');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ if (await this.mock.proposalNeedsQueuing(this.proposal.id)) {
+ expect(await this.helper.queue())
+ .to.emit(this.mock, 'ProposalQueued')
+ .withArgs(this.proposal.id, anyValue);
+ }
+ if (delay > 0) {
+ await this.helper.waitForEta();
+ }
+ await expect(this.helper.execute())
+ .to.emit(this.mock, 'ProposalExecuted')
+ .withArgs(this.proposal.id)
+ .to.emit(this.receiver, 'CalledUnrestricted');
+ });
+ }
+ });
+
+ it('reverts when an operation is executed before eta', async function () {
+ const delay = time.duration.hours(2n);
+ await this.mock.$_setBaseDelaySeconds(delay);
+
+ this.proposal = await this.helper.setProposal([this.unrestricted.operation], 'descr');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnmetDelay')
+ .withArgs(this.proposal.id, await this.mock.proposalEta(this.proposal.id));
+ });
+
+ it('reverts with a proposal including multiple operations but one of those was cancelled in the manager', async function () {
+ const delay = time.duration.hours(2n);
+ const roleId = 1n;
+
+ await this.manager.connect(this.admin).setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, delay);
+
+ // Set proposals
+ const original = new GovernorHelper(this.mock, mode);
+ await original.setProposal([this.restricted.operation, this.unrestricted.operation], 'descr');
+
+ // Go through all the governance process
+ await original.propose();
+ await original.waitForSnapshot();
+ await original.connect(this.voter1).vote({ support: VoteType.For });
+ await original.waitForDeadline();
+ await original.queue();
+ await original.waitForEta();
+
+ // Suddenly cancel one of the proposed operations in the manager
+ await this.manager
+ .connect(this.admin)
+ .cancel(this.mock, this.restricted.operation.target, this.restricted.operation.data);
+
+ // Reschedule the same operation in a different proposal to avoid "AccessManagerNotScheduled" error
+ const rescheduled = new GovernorHelper(this.mock, mode);
+ await rescheduled.setProposal([this.restricted.operation], 'descr');
+ await rescheduled.propose();
+ await rescheduled.waitForSnapshot();
+ await rescheduled.connect(this.voter1).vote({ support: VoteType.For });
+ await rescheduled.waitForDeadline();
+ await rescheduled.queue(); // This will schedule it again in the manager
+ await rescheduled.waitForEta();
+
+ // Attempt to execute
+ await expect(original.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorMismatchedNonce')
+ .withArgs(original.currentProposal.id, 1, 2);
+ });
+
+ it('single operation with access manager delay', async function () {
+ const delay = 1000n;
+ const roleId = 1n;
+
+ await this.manager.connect(this.admin).setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, delay);
+
+ this.proposal = await this.helper.setProposal([this.restricted.operation], 'descr');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ const txQueue = await this.helper.queue();
+ await this.helper.waitForEta();
+ const txExecute = await this.helper.execute();
+
+ await expect(txQueue)
+ .to.emit(this.mock, 'ProposalQueued')
+ .withArgs(this.proposal.id, anyValue)
+ .to.emit(this.manager, 'OperationScheduled')
+ .withArgs(
+ this.restricted.id,
+ 1n,
+ (await time.clockFromReceipt.timestamp(txQueue)) + delay,
+ this.mock.target,
+ this.restricted.operation.target,
+ this.restricted.operation.data,
+ );
+
+ await expect(txExecute)
+ .to.emit(this.mock, 'ProposalExecuted')
+ .withArgs(this.proposal.id)
+ .to.emit(this.manager, 'OperationExecuted')
+ .withArgs(this.restricted.id, 1n)
+ .to.emit(this.receiver, 'CalledRestricted');
+ });
+
+ it('bundle of varied operations', async function () {
+ const managerDelay = 1000n;
+ const roleId = 1n;
+ const baseDelay = managerDelay * 2n;
+
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ await this.manager.connect(this.admin).setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, managerDelay);
+
+ this.proposal = await this.helper.setProposal(
+ [this.restricted.operation, this.unrestricted.operation, this.fallback.operation],
+ 'descr',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ const txQueue = await this.helper.queue();
+ await this.helper.waitForEta();
+ const txExecute = await this.helper.execute();
+
+ await expect(txQueue)
+ .to.emit(this.mock, 'ProposalQueued')
+ .withArgs(this.proposal.id, anyValue)
+ .to.emit(this.manager, 'OperationScheduled')
+ .withArgs(
+ this.restricted.id,
+ 1n,
+ (await time.clockFromReceipt.timestamp(txQueue)) + baseDelay,
+ this.mock.target,
+ this.restricted.operation.target,
+ this.restricted.operation.data,
+ );
+
+ await expect(txExecute)
+ .to.emit(this.mock, 'ProposalExecuted')
+ .withArgs(this.proposal.id)
+ .to.emit(this.manager, 'OperationExecuted')
+ .withArgs(this.restricted.id, 1n)
+ .to.emit(this.receiver, 'CalledRestricted')
+ .to.emit(this.receiver, 'CalledUnrestricted')
+ .to.emit(this.receiver, 'CalledFallback');
+ });
+
+ describe('cancel', function () {
+ const delay = 1000n;
+ const roleId = 1n;
+
+ beforeEach(async function () {
+ await this.manager
+ .connect(this.admin)
+ .setTargetFunctionRole(this.receiver, [this.restricted.selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, delay);
+ });
+
+ it('cancels restricted with delay after queue (internal)', async function () {
+ this.proposal = await this.helper.setProposal([this.restricted.operation], 'descr');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id)
+ .to.emit(this.manager, 'OperationCanceled')
+ .withArgs(this.restricted.id, 1n);
+
+ await this.helper.waitForEta();
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('cancels restricted with queueing if the same operation is part of a more recent proposal (internal)', async function () {
+ // Set proposals
+ const original = new GovernorHelper(this.mock, mode);
+ await original.setProposal([this.restricted.operation], 'descr');
+
+ // Go through all the governance process
+ await original.propose();
+ await original.waitForSnapshot();
+ await original.connect(this.voter1).vote({ support: VoteType.For });
+ await original.waitForDeadline();
+ await original.queue();
+
+ // Cancel the operation in the manager
+ await this.manager
+ .connect(this.admin)
+ .cancel(this.mock, this.restricted.operation.target, this.restricted.operation.data);
+
+ // Another proposal is added with the same operation
+ const rescheduled = new GovernorHelper(this.mock, mode);
+ await rescheduled.setProposal([this.restricted.operation], 'another descr');
+
+ // Queue the new proposal
+ await rescheduled.propose();
+ await rescheduled.waitForSnapshot();
+ await rescheduled.connect(this.voter1).vote({ support: VoteType.For });
+ await rescheduled.waitForDeadline();
+ await rescheduled.queue(); // This will schedule it again in the manager
+
+ // Cancel
+ const eta = await this.mock.proposalEta(rescheduled.currentProposal.id);
+
+ await expect(original.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(original.currentProposal.id);
+
+ await time.clock.timestamp().then(clock => time.increaseTo.timestamp(max(clock + 1n, eta)));
+
+ await expect(original.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ original.currentProposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('cancels unrestricted with queueing (internal)', async function () {
+ this.proposal = await this.helper.setProposal([this.unrestricted.operation], 'descr');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ const eta = await this.mock.proposalEta(this.proposal.id);
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+
+ await time.clock.timestamp().then(clock => time.increaseTo.timestamp(max(clock + 1n, eta)));
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('cancels unrestricted without queueing (internal)', async function () {
+ this.proposal = await this.helper.setProposal([this.unrestricted.operation], 'descr');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('cancels calls already canceled by guardian', async function () {
+ const operationA = { target: this.receiver.target, data: this.restricted.selector + '00' };
+ const operationB = { target: this.receiver.target, data: this.restricted.selector + '01' };
+ const operationC = { target: this.receiver.target, data: this.restricted.selector + '02' };
+ const operationAId = hashOperation(this.mock.target, operationA.target, operationA.data);
+ const operationBId = hashOperation(this.mock.target, operationB.target, operationB.data);
+
+ const proposal1 = new GovernorHelper(this.mock, mode);
+ const proposal2 = new GovernorHelper(this.mock, mode);
+ proposal1.setProposal([operationA, operationB], 'proposal A+B');
+ proposal2.setProposal([operationA, operationC], 'proposal A+C');
+
+ for (const p of [proposal1, proposal2]) {
+ await p.propose();
+ await p.waitForSnapshot();
+ await p.connect(this.voter1).vote({ support: VoteType.For });
+ await p.waitForDeadline();
+ }
+
+ // Can queue the first proposal
+ await proposal1.queue();
+
+ // Cannot queue the second proposal: operation A already scheduled with delay
+ await expect(proposal2.queue())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerAlreadyScheduled')
+ .withArgs(operationAId);
+
+ // Admin cancels operation B on the manager
+ await this.manager.connect(this.admin).cancel(this.mock, operationB.target, operationB.data);
+
+ // Still cannot queue the second proposal: operation A already scheduled with delay
+ await expect(proposal2.queue())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerAlreadyScheduled')
+ .withArgs(operationAId);
+
+ await proposal1.waitForEta();
+
+ // Cannot execute first proposal: operation B has been canceled
+ await expect(proposal1.execute())
+ .to.be.revertedWithCustomError(this.manager, 'AccessManagerNotScheduled')
+ .withArgs(operationBId);
+
+ // Cancel the first proposal to release operation A
+ await proposal1.cancel('internal');
+
+ // can finally queue the second proposal
+ await proposal2.queue();
+
+ await proposal2.waitForEta();
+
+ // Can execute second proposal
+ await proposal2.execute();
+ });
+ });
+
+ describe('ignore AccessManager', function () {
+ it('defaults', async function () {
+ expect(await this.mock.isAccessManagerIgnored(this.receiver, this.restricted.selector)).to.be.false;
+ expect(await this.mock.isAccessManagerIgnored(this.mock, '0x12341234')).to.be.true;
+ });
+
+ it('internal setter', async function () {
+ await expect(this.mock.$_setAccessManagerIgnored(this.receiver, this.restricted.selector, true))
+ .to.emit(this.mock, 'AccessManagerIgnoredSet')
+ .withArgs(this.receiver, this.restricted.selector, true);
+
+ expect(await this.mock.isAccessManagerIgnored(this.receiver, this.restricted.selector)).to.be.true;
+
+ await expect(this.mock.$_setAccessManagerIgnored(this.mock, '0x12341234', false))
+ .to.emit(this.mock, 'AccessManagerIgnoredSet')
+ .withArgs(this.mock, '0x12341234', false);
+
+ expect(await this.mock.isAccessManagerIgnored(this.mock, '0x12341234')).to.be.false;
+ });
+
+ it('external setter', async function () {
+ const setAccessManagerIgnored = (...args) =>
+ this.mock.interface.encodeFunctionData('setAccessManagerIgnored', args);
+
+ await this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: setAccessManagerIgnored(
+ this.receiver.target,
+ [this.restricted.selector, this.unrestricted.selector],
+ true,
+ ),
+ },
+ {
+ target: this.mock.target,
+ data: setAccessManagerIgnored(this.mock.target, ['0x12341234', '0x67896789'], false),
+ },
+ ],
+ 'descr',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute()).to.emit(this.mock, 'AccessManagerIgnoredSet');
+
+ expect(await this.mock.isAccessManagerIgnored(this.receiver, this.restricted.selector)).to.be.true;
+ expect(await this.mock.isAccessManagerIgnored(this.receiver, this.unrestricted.selector)).to.be.true;
+ expect(await this.mock.isAccessManagerIgnored(this.mock, '0x12341234')).to.be.false;
+ expect(await this.mock.isAccessManagerIgnored(this.mock, '0x67896789')).to.be.false;
+ });
+
+ it('locked function', async function () {
+ const setAccessManagerIgnored = selector('setAccessManagerIgnored(address,bytes4[],bool)');
+
+ await expect(
+ this.mock.$_setAccessManagerIgnored(this.mock, setAccessManagerIgnored, true),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorLockedIgnore');
+
+ await this.mock.$_setAccessManagerIgnored(this.receiver, setAccessManagerIgnored, true);
+ });
+
+ it('ignores access manager', async function () {
+ const amount = 100n;
+ const target = this.token.target;
+ const data = this.token.interface.encodeFunctionData('transfer', [this.voter4.address, amount]);
+ const selector = data.slice(0, 10);
+ await this.token.$_mint(this.mock, amount);
+
+ const roleId = 1n;
+ await this.manager.connect(this.admin).setTargetFunctionRole(target, [selector], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, 0);
+
+ await this.helper.setProposal([{ target, data }], 'descr #1');
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.manager, 0n, amount);
+
+ await this.mock.$_setAccessManagerIgnored(target, selector, true);
+
+ await this.helper.setProposal([{ target, data }], 'descr #2');
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute()).to.emit(this.token, 'Transfer').withArgs(this.mock, this.voter4, amount);
+ });
+ });
+
+ describe('operating on an Ownable contract', function () {
+ const method = selector('$_checkOwner()');
+
+ beforeEach(async function () {
+ this.ownable = await ethers.deployContract('$Ownable', [this.manager]);
+ this.operation = {
+ target: this.ownable.target,
+ data: this.ownable.interface.encodeFunctionData('$_checkOwner'),
+ };
+ });
+
+ it('succeeds with delay', async function () {
+ const roleId = 1n;
+ const executionDelay = time.duration.hours(2n);
+ const baseDelay = time.duration.hours(1n);
+
+ // Set execution delay
+ await this.manager.connect(this.admin).setTargetFunctionRole(this.ownable, [method], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ await this.helper.setProposal([this.operation], `descr`);
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+ await this.helper.execute(); // Don't revert
+ });
+
+ it('succeeds without delay', async function () {
+ const roleId = 1n;
+ const executionDelay = 0n;
+ const baseDelay = 0n;
+
+ // Set execution delay
+ await this.manager.connect(this.admin).setTargetFunctionRole(this.ownable, [method], roleId);
+ await this.manager.connect(this.admin).grantRole(roleId, this.mock, executionDelay);
+
+ // Set base delay
+ await this.mock.$_setBaseDelaySeconds(baseDelay);
+
+ await this.helper.setProposal([this.operation], `descr`);
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.execute(); // Don't revert
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockCompound.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockCompound.test.js
new file mode 100644
index 000000000..545bf359d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockCompound.test.js
@@ -0,0 +1,448 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { ProposalState, VoteType } = require('../../helpers/enums');
+const time = require('../../helpers/time');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+const defaultDelay = time.duration.days(2n);
+
+describe('GovernorTimelockCompound', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [deployer, owner, voter1, voter2, voter3, voter4, other] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const predictGovernor = await deployer
+ .getNonce()
+ .then(nonce => ethers.getCreateAddress({ from: deployer.address, nonce: nonce + 1 }));
+ const timelock = await ethers.deployContract('CompTimelock', [predictGovernor, defaultDelay]);
+ const mock = await ethers.deployContract('$GovernorTimelockCompoundMock', [
+ name,
+ votingDelay,
+ votingPeriod,
+ 0n,
+ timelock,
+ token,
+ 0n,
+ ]);
+
+ await owner.sendTransaction({ to: timelock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { deployer, owner, voter1, voter2, voter3, voter4, other, receiver, token, mock, timelock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // default proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ value,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ },
+ ],
+ '',
+ );
+ });
+
+ it("doesn't accept ether transfers", async function () {
+ await expect(this.owner.sendTransaction({ to: this.mock, value: 1n })).to.be.revertedWithCustomError(
+ this.mock,
+ 'GovernorDisabledDeposit',
+ );
+ });
+
+ it('post deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0n)).to.equal(0n);
+
+ expect(await this.mock.timelock()).to.equal(this.timelock);
+ expect(await this.timelock.admin()).to.equal(this.mock);
+ });
+
+ it('nominal', async function () {
+ expect(await this.mock.proposalEta(this.proposal.id)).to.equal(0n);
+ expect(await this.mock.proposalNeedsQueuing(this.proposal.id)).to.be.true;
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+ const txQueue = await this.helper.queue();
+
+ const eta = (await time.clockFromReceipt.timestamp(txQueue)) + defaultDelay;
+ expect(await this.mock.proposalEta(this.proposal.id)).to.equal(eta);
+ expect(await this.mock.proposalNeedsQueuing(this.proposal.id)).to.be.true;
+
+ await this.helper.waitForEta();
+ const txExecute = await this.helper.execute();
+
+ await expect(txQueue)
+ .to.emit(this.mock, 'ProposalQueued')
+ .withArgs(this.proposal.id, eta)
+ .to.emit(this.timelock, 'QueueTransaction')
+ .withArgs(...Array(5).fill(anyValue), eta);
+
+ await expect(txExecute)
+ .to.emit(this.mock, 'ProposalExecuted')
+ .withArgs(this.proposal.id)
+ .to.emit(this.timelock, 'ExecuteTransaction')
+ .withArgs(...Array(5).fill(anyValue), eta)
+ .to.emit(this.receiver, 'MockFunctionCalled');
+ });
+
+ describe('should revert', function () {
+ describe('on queue', function () {
+ it('if already queued', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await expect(this.helper.queue())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Queued,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]),
+ );
+ });
+
+ it('if proposal contains duplicate calls', async function () {
+ const action = {
+ target: this.token.target,
+ data: this.token.interface.encodeFunctionData('approve', [this.receiver.target, ethers.MaxUint256]),
+ };
+ const { id } = this.helper.setProposal([action, action], '');
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await expect(this.helper.queue())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorAlreadyQueuedProposal')
+ .withArgs(id);
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNotQueuedProposal')
+ .withArgs(id);
+ });
+ });
+
+ describe('on execute', function () {
+ it('if not queued', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline(1n);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Succeeded);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorNotQueuedProposal')
+ .withArgs(this.proposal.id);
+ });
+
+ it('if too early', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Queued);
+
+ await expect(this.helper.execute()).to.be.rejectedWith(
+ "Timelock::executeTransaction: Transaction hasn't surpassed time lock",
+ );
+ });
+
+ it('if too late', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta(time.duration.days(30));
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Expired);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Expired,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('if already executed', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+ await this.helper.execute();
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Executed,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+ });
+
+ describe('on safe receive', function () {
+ describe('ERC721', function () {
+ const tokenId = 1n;
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC721', ['Non Fungible Token', 'NFT']);
+ await this.token.$_mint(this.owner, tokenId);
+ });
+
+ it("can't receive an ERC721 safeTransfer", async function () {
+ await expect(
+ this.token.connect(this.owner).safeTransferFrom(this.owner, this.mock, tokenId),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorDisabledDeposit');
+ });
+ });
+
+ describe('ERC1155', function () {
+ const tokenIds = {
+ 1: 1000n,
+ 2: 2000n,
+ 3: 3000n,
+ };
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC1155', ['https://token-cdn-domain/{id}.json']);
+ await this.token.$_mintBatch(this.owner, Object.keys(tokenIds), Object.values(tokenIds), '0x');
+ });
+
+ it("can't receive ERC1155 safeTransfer", async function () {
+ await expect(
+ this.token.connect(this.owner).safeTransferFrom(
+ this.owner,
+ this.mock,
+ ...Object.entries(tokenIds)[0], // id + amount
+ '0x',
+ ),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorDisabledDeposit');
+ });
+
+ it("can't receive ERC1155 safeBatchTransfer", async function () {
+ await expect(
+ this.token
+ .connect(this.owner)
+ .safeBatchTransferFrom(this.owner, this.mock, Object.keys(tokenIds), Object.values(tokenIds), '0x'),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorDisabledDeposit');
+ });
+ });
+ });
+ });
+
+ describe('cancel', function () {
+ it('cancel before queue prevents scheduling', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await expect(this.helper.queue())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]),
+ );
+ });
+
+ it('cancel after queue prevents executing', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+ });
+
+ describe('onlyGovernance', function () {
+ describe('relay', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.mock, 1);
+ });
+
+ it('is protected', async function () {
+ await expect(
+ this.mock
+ .connect(this.owner)
+ .relay(this.token, 0, this.token.interface.encodeFunctionData('transfer', [this.other.address, 1n])),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can be executed through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('relay', [
+ this.token.target,
+ 0n,
+ this.token.interface.encodeFunctionData('transfer', [this.other.address, 1n]),
+ ]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ const txExecute = this.helper.execute();
+
+ await expect(txExecute).to.changeTokenBalances(this.token, [this.mock, this.other], [-1n, 1n]);
+
+ await expect(txExecute).to.emit(this.token, 'Transfer').withArgs(this.mock, this.other, 1n);
+ });
+ });
+
+ describe('updateTimelock', function () {
+ beforeEach(async function () {
+ this.newTimelock = await ethers.deployContract('CompTimelock', [this.mock, time.duration.days(7n)]);
+ });
+
+ it('is protected', async function () {
+ await expect(this.mock.connect(this.owner).updateTimelock(this.newTimelock))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can be executed through governance to', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.timelock.target,
+ data: this.timelock.interface.encodeFunctionData('setPendingAdmin', [this.owner.address]),
+ },
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('updateTimelock', [this.newTimelock.target]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ await expect(this.helper.execute())
+ .to.emit(this.mock, 'TimelockChange')
+ .withArgs(this.timelock, this.newTimelock);
+
+ expect(await this.mock.timelock()).to.equal(this.newTimelock);
+ });
+ });
+
+ it('can transfer timelock to new governor', async function () {
+ const newGovernor = await ethers.deployContract('$GovernorTimelockCompoundMock', [
+ name,
+ 8n,
+ 32n,
+ 0n,
+ this.timelock,
+ this.token,
+ 0n,
+ ]);
+
+ this.helper.setProposal(
+ [
+ {
+ target: this.timelock.target,
+ data: this.timelock.interface.encodeFunctionData('setPendingAdmin', [newGovernor.target]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ await expect(this.helper.execute()).to.emit(this.timelock, 'NewPendingAdmin').withArgs(newGovernor);
+
+ await newGovernor.__acceptAdmin();
+ expect(await this.timelock.admin()).to.equal(newGovernor);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockControl.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockControl.test.js
new file mode 100644
index 000000000..c1156a509
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorTimelockControl.test.js
@@ -0,0 +1,504 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { GovernorHelper, timelockSalt } = require('../../helpers/governance');
+const { OperationState, ProposalState, VoteType } = require('../../helpers/enums');
+const time = require('../../helpers/time');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const DEFAULT_ADMIN_ROLE = ethers.ZeroHash;
+const PROPOSER_ROLE = ethers.id('PROPOSER_ROLE');
+const EXECUTOR_ROLE = ethers.id('EXECUTOR_ROLE');
+const CANCELLER_ROLE = ethers.id('CANCELLER_ROLE');
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+const delay = time.duration.hours(1n);
+
+describe('GovernorTimelockControl', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [deployer, owner, voter1, voter2, voter3, voter4, other] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const timelock = await ethers.deployContract('TimelockController', [delay, [], [], deployer]);
+ const mock = await ethers.deployContract('$GovernorTimelockControlMock', [
+ name,
+ votingDelay,
+ votingPeriod,
+ 0n,
+ timelock,
+ token,
+ 0n,
+ ]);
+
+ await owner.sendTransaction({ to: timelock, value });
+ await token.$_mint(owner, tokenSupply);
+ await timelock.grantRole(PROPOSER_ROLE, mock);
+ await timelock.grantRole(PROPOSER_ROLE, owner);
+ await timelock.grantRole(CANCELLER_ROLE, mock);
+ await timelock.grantRole(CANCELLER_ROLE, owner);
+ await timelock.grantRole(EXECUTOR_ROLE, ethers.ZeroAddress);
+ await timelock.revokeRole(DEFAULT_ADMIN_ROLE, deployer);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { deployer, owner, voter1, voter2, voter3, voter4, other, receiver, token, mock, timelock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // default proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ value,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ },
+ ],
+ '',
+ );
+
+ this.proposal.timelockid = await this.timelock.hashOperationBatch(
+ ...this.proposal.shortProposal.slice(0, 3),
+ ethers.ZeroHash,
+ timelockSalt(this.mock.target, this.proposal.shortProposal[3]),
+ );
+ });
+
+ it("doesn't accept ether transfers", async function () {
+ await expect(this.owner.sendTransaction({ to: this.mock, value: 1n })).to.be.revertedWithCustomError(
+ this.mock,
+ 'GovernorDisabledDeposit',
+ );
+ });
+
+ it('post deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0n)).to.equal(0n);
+
+ expect(await this.mock.timelock()).to.equal(this.timelock);
+ });
+
+ it('nominal', async function () {
+ expect(await this.mock.proposalEta(this.proposal.id)).to.equal(0n);
+ expect(await this.mock.proposalNeedsQueuing(this.proposal.id)).to.be.true;
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+
+ expect(await this.mock.proposalNeedsQueuing(this.proposal.id)).to.be.true;
+ const txQueue = await this.helper.queue();
+
+ const eta = (await time.clockFromReceipt.timestamp(txQueue)) + delay;
+ expect(await this.mock.proposalEta(this.proposal.id)).to.equal(eta);
+ await this.helper.waitForEta();
+
+ const txExecute = this.helper.execute();
+
+ await expect(txQueue)
+ .to.emit(this.mock, 'ProposalQueued')
+ .withArgs(this.proposal.id, anyValue)
+ .to.emit(this.timelock, 'CallScheduled')
+ .withArgs(this.proposal.timelockid, ...Array(6).fill(anyValue))
+ .to.emit(this.timelock, 'CallSalt')
+ .withArgs(this.proposal.timelockid, anyValue);
+
+ await expect(txExecute)
+ .to.emit(this.mock, 'ProposalExecuted')
+ .withArgs(this.proposal.id)
+ .to.emit(this.timelock, 'CallExecuted')
+ .withArgs(this.proposal.timelockid, ...Array(4).fill(anyValue))
+ .to.emit(this.receiver, 'MockFunctionCalled');
+ });
+
+ describe('should revert', function () {
+ describe('on queue', function () {
+ it('if already queued', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await expect(this.helper.queue())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Queued,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]),
+ );
+ });
+ });
+
+ describe('on execute', function () {
+ it('if not queued', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline(1n);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Succeeded);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.timelock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.proposal.timelockid, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ it('if too early', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Queued);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.timelock, 'TimelockUnexpectedOperationState')
+ .withArgs(this.proposal.timelockid, GovernorHelper.proposalStatesToBitMap(OperationState.Ready));
+ });
+
+ it('if already executed', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+ await this.helper.execute();
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Executed,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('if already executed by another proposer', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ await this.timelock.executeBatch(
+ ...this.proposal.shortProposal.slice(0, 3),
+ ethers.ZeroHash,
+ timelockSalt(this.mock.target, this.proposal.shortProposal[3]),
+ );
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Executed,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+ });
+ });
+
+ describe('cancel', function () {
+ it('cancel before queue prevents scheduling', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await expect(this.helper.queue())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded]),
+ );
+ });
+
+ it('cancel after queue prevents executing', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ await expect(this.helper.cancel('internal'))
+ .to.emit(this.mock, 'ProposalCanceled')
+ .withArgs(this.proposal.id);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Canceled,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ it('cancel on timelock is reflected on governor', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Queued);
+
+ await expect(this.timelock.connect(this.owner).cancel(this.proposal.timelockid))
+ .to.emit(this.timelock, 'Cancelled')
+ .withArgs(this.proposal.timelockid);
+
+ expect(await this.mock.state(this.proposal.id)).to.equal(ProposalState.Canceled);
+ });
+ });
+
+ describe('onlyGovernance', function () {
+ describe('relay', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.mock, 1);
+ });
+
+ it('is protected', async function () {
+ await expect(
+ this.mock
+ .connect(this.owner)
+ .relay(this.token, 0n, this.token.interface.encodeFunctionData('transfer', [this.other.address, 1n])),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can be executed through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('relay', [
+ this.token.target,
+ 0n,
+ this.token.interface.encodeFunctionData('transfer', [this.other.address, 1n]),
+ ]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ const txExecute = await this.helper.execute();
+
+ await expect(txExecute).to.changeTokenBalances(this.token, [this.mock, this.other], [-1n, 1n]);
+
+ await expect(txExecute).to.emit(this.token, 'Transfer').withArgs(this.mock, this.other, 1n);
+ });
+
+ it('is payable and can transfer eth to EOA', async function () {
+ const t2g = 128n; // timelock to governor
+ const g2o = 100n; // governor to eoa (other)
+
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ value: t2g,
+ data: this.mock.interface.encodeFunctionData('relay', [this.other.address, g2o, '0x']),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ await expect(this.helper.execute()).to.changeEtherBalances(
+ [this.timelock, this.mock, this.other],
+ [-t2g, t2g - g2o, g2o],
+ );
+ });
+
+ it('protected against other proposers', async function () {
+ const call = [
+ this.mock,
+ 0n,
+ this.mock.interface.encodeFunctionData('relay', [ethers.ZeroAddress, 0n, '0x']),
+ ethers.ZeroHash,
+ ethers.ZeroHash,
+ ];
+
+ await this.timelock.connect(this.owner).schedule(...call, delay);
+
+ await time.increaseBy.timestamp(delay);
+
+ // Error bubbled up from Governor
+ await expect(this.timelock.connect(this.owner).execute(...call)).to.be.revertedWithPanic(
+ PANIC_CODES.POP_ON_EMPTY_ARRAY,
+ );
+ });
+ });
+
+ describe('updateTimelock', function () {
+ beforeEach(async function () {
+ this.newTimelock = await ethers.deployContract('TimelockController', [
+ delay,
+ [this.mock],
+ [this.mock],
+ ethers.ZeroAddress,
+ ]);
+ });
+
+ it('is protected', async function () {
+ await expect(this.mock.connect(this.owner).updateTimelock(this.newTimelock))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can be executed through governance to', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('updateTimelock', [this.newTimelock.target]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+
+ await expect(this.helper.execute())
+ .to.emit(this.mock, 'TimelockChange')
+ .withArgs(this.timelock, this.newTimelock);
+
+ expect(await this.mock.timelock()).to.equal(this.newTimelock);
+ });
+ });
+
+ describe('on safe receive', function () {
+ describe('ERC721', function () {
+ const tokenId = 1n;
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC721', ['Non Fungible Token', 'NFT']);
+ await this.token.$_mint(this.owner, tokenId);
+ });
+
+ it("can't receive an ERC721 safeTransfer", async function () {
+ await expect(
+ this.token.connect(this.owner).safeTransferFrom(this.owner, this.mock, tokenId),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorDisabledDeposit');
+ });
+ });
+
+ describe('ERC1155', function () {
+ const tokenIds = {
+ 1: 1000n,
+ 2: 2000n,
+ 3: 3000n,
+ };
+
+ beforeEach(async function () {
+ this.token = await ethers.deployContract('$ERC1155', ['https://token-cdn-domain/{id}.json']);
+ await this.token.$_mintBatch(this.owner, Object.keys(tokenIds), Object.values(tokenIds), '0x');
+ });
+
+ it("can't receive ERC1155 safeTransfer", async function () {
+ await expect(
+ this.token.connect(this.owner).safeTransferFrom(
+ this.owner,
+ this.mock,
+ ...Object.entries(tokenIds)[0], // id + amount
+ '0x',
+ ),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorDisabledDeposit');
+ });
+
+ it("can't receive ERC1155 safeBatchTransfer", async function () {
+ await expect(
+ this.token
+ .connect(this.owner)
+ .safeBatchTransferFrom(this.owner, this.mock, Object.keys(tokenIds), Object.values(tokenIds), '0x'),
+ ).to.be.revertedWithCustomError(this.mock, 'GovernorDisabledDeposit');
+ });
+ });
+ });
+ });
+
+ it('clear queue of pending governor calls', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('nonGovernanceFunction'),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.queue();
+ await this.helper.waitForEta();
+ await this.helper.execute();
+
+ // This path clears _governanceCall as part of the afterExecute call,
+ // but we have not way to check that the cleanup actually happened other
+ // then coverage reports.
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorVotesQuorumFraction.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorVotesQuorumFraction.test.js
new file mode 100644
index 000000000..368e396f9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorVotesQuorumFraction.test.js
@@ -0,0 +1,165 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { ProposalState, VoteType } = require('../../helpers/enums');
+const time = require('../../helpers/time');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const ratio = 8n; // percents
+const newRatio = 6n; // percents
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+describe('GovernorVotesQuorumFraction', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, voter1, voter2, voter3, voter4] = await ethers.getSigners();
+
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorMock', [name, votingDelay, votingPeriod, 0n, token, ratio]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { owner, voter1, voter2, voter3, voter4, receiver, token, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // default proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ value,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ },
+ ],
+ '',
+ );
+ });
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ expect(await this.mock.quorum(0)).to.equal(0n);
+ expect(await this.mock.quorumNumerator()).to.equal(ratio);
+ expect(await this.mock.quorumDenominator()).to.equal(100n);
+ expect(await time.clock[mode]().then(clock => this.mock.quorum(clock - 1n))).to.equal(
+ (tokenSupply * ratio) / 100n,
+ );
+ });
+
+ it('quorum reached', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+ });
+
+ it('quorum not reached', async function () {
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorUnexpectedProposalState')
+ .withArgs(
+ this.proposal.id,
+ ProposalState.Defeated,
+ GovernorHelper.proposalStatesToBitMap([ProposalState.Succeeded, ProposalState.Queued]),
+ );
+ });
+
+ describe('onlyGovernance updates', function () {
+ it('updateQuorumNumerator is protected', async function () {
+ await expect(this.mock.connect(this.owner).updateQuorumNumerator(newRatio))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorOnlyExecutor')
+ .withArgs(this.owner);
+ });
+
+ it('can updateQuorumNumerator through governance', async function () {
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('updateQuorumNumerator', [newRatio]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ await expect(this.helper.execute()).to.emit(this.mock, 'QuorumNumeratorUpdated').withArgs(ratio, newRatio);
+
+ expect(await this.mock.quorumNumerator()).to.equal(newRatio);
+ expect(await this.mock.quorumDenominator()).to.equal(100n);
+
+ // it takes one block for the new quorum to take effect
+ expect(await time.clock[mode]().then(blockNumber => this.mock.quorum(blockNumber - 1n))).to.equal(
+ (tokenSupply * ratio) / 100n,
+ );
+
+ await mine();
+
+ expect(await time.clock[mode]().then(blockNumber => this.mock.quorum(blockNumber - 1n))).to.equal(
+ (tokenSupply * newRatio) / 100n,
+ );
+ });
+
+ it('cannot updateQuorumNumerator over the maximum', async function () {
+ const quorumNumerator = 101n;
+ this.helper.setProposal(
+ [
+ {
+ target: this.mock.target,
+ data: this.mock.interface.encodeFunctionData('updateQuorumNumerator', [quorumNumerator]),
+ },
+ ],
+ '',
+ );
+
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For });
+ await this.helper.waitForDeadline();
+
+ const quorumDenominator = await this.mock.quorumDenominator();
+
+ await expect(this.helper.execute())
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidQuorumFraction')
+ .withArgs(quorumNumerator, quorumDenominator);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorWithParams.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorWithParams.test.js
new file mode 100644
index 000000000..37e15f5c2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/extensions/GovernorWithParams.test.js
@@ -0,0 +1,245 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { GovernorHelper } = require('../../helpers/governance');
+const { VoteType } = require('../../helpers/enums');
+const { getDomain, ExtendedBallot } = require('../../helpers/eip712');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'OZ-Governor';
+const version = '1';
+const tokenName = 'MockToken';
+const tokenSymbol = 'MTKN';
+const tokenSupply = ethers.parseEther('100');
+const votingDelay = 4n;
+const votingPeriod = 16n;
+const value = ethers.parseEther('1');
+
+const params = {
+ decoded: [42n, 'These are my params'],
+ encoded: ethers.AbiCoder.defaultAbiCoder().encode(['uint256', 'string'], [42n, 'These are my params']),
+};
+
+describe('GovernorWithParams', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ const [owner, proposer, voter1, voter2, voter3, voter4, other] = await ethers.getSigners();
+ const receiver = await ethers.deployContract('CallReceiverMock');
+
+ const token = await ethers.deployContract(Token, [tokenName, tokenSymbol, version]);
+ const mock = await ethers.deployContract('$GovernorWithParamsMock', [name, token]);
+
+ await owner.sendTransaction({ to: mock, value });
+ await token.$_mint(owner, tokenSupply);
+
+ const helper = new GovernorHelper(mock, mode);
+ await helper.connect(owner).delegate({ token, to: voter1, value: ethers.parseEther('10') });
+ await helper.connect(owner).delegate({ token, to: voter2, value: ethers.parseEther('7') });
+ await helper.connect(owner).delegate({ token, to: voter3, value: ethers.parseEther('5') });
+ await helper.connect(owner).delegate({ token, to: voter4, value: ethers.parseEther('2') });
+
+ return { owner, proposer, voter1, voter2, voter3, voter4, other, receiver, token, mock, helper };
+ };
+
+ describe(`using ${Token}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+
+ // default proposal
+ this.proposal = this.helper.setProposal(
+ [
+ {
+ target: this.receiver.target,
+ value,
+ data: this.receiver.interface.encodeFunctionData('mockFunction'),
+ },
+ ],
+ '',
+ );
+ });
+
+ it('deployment check', async function () {
+ expect(await this.mock.name()).to.equal(name);
+ expect(await this.mock.token()).to.equal(this.token);
+ expect(await this.mock.votingDelay()).to.equal(votingDelay);
+ expect(await this.mock.votingPeriod()).to.equal(votingPeriod);
+ });
+
+ it('nominal is unaffected', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+ await this.helper.connect(this.voter1).vote({ support: VoteType.For, reason: 'This is nice' });
+ await this.helper.connect(this.voter2).vote({ support: VoteType.For });
+ await this.helper.connect(this.voter3).vote({ support: VoteType.Against });
+ await this.helper.connect(this.voter4).vote({ support: VoteType.Abstain });
+ await this.helper.waitForDeadline();
+ await this.helper.execute();
+
+ expect(await this.mock.hasVoted(this.proposal.id, this.owner)).to.be.false;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter1)).to.be.true;
+ expect(await this.mock.hasVoted(this.proposal.id, this.voter2)).to.be.true;
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ expect(await ethers.provider.getBalance(this.receiver)).to.equal(value);
+ });
+
+ it('Voting with params is properly supported', async function () {
+ await this.helper.connect(this.proposer).propose();
+ await this.helper.waitForSnapshot();
+
+ const weight = ethers.parseEther('7') - params.decoded[0];
+
+ await expect(
+ this.helper.connect(this.voter2).vote({
+ support: VoteType.For,
+ reason: 'no particular reason',
+ params: params.encoded,
+ }),
+ )
+ .to.emit(this.mock, 'CountParams')
+ .withArgs(...params.decoded)
+ .to.emit(this.mock, 'VoteCastWithParams')
+ .withArgs(
+ this.voter2.address,
+ this.proposal.id,
+ VoteType.For,
+ weight,
+ 'no particular reason',
+ params.encoded,
+ );
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([0n, weight, 0n]);
+ });
+
+ describe('voting by signature', function () {
+ it('supports EOA signatures', async function () {
+ await this.token.connect(this.voter2).delegate(this.other);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+
+ // Prepare vote
+ const weight = ethers.parseEther('7') - params.decoded[0];
+ const nonce = await this.mock.nonces(this.other);
+ const data = {
+ proposalId: this.proposal.id,
+ support: VoteType.For,
+ voter: this.other.address,
+ nonce,
+ reason: 'no particular reason',
+ params: params.encoded,
+ signature: (contract, message) =>
+ getDomain(contract).then(domain => this.other.signTypedData(domain, { ExtendedBallot }, message)),
+ };
+
+ // Vote
+ await expect(this.helper.vote(data))
+ .to.emit(this.mock, 'CountParams')
+ .withArgs(...params.decoded)
+ .to.emit(this.mock, 'VoteCastWithParams')
+ .withArgs(data.voter, data.proposalId, data.support, weight, data.reason, data.params);
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([0n, weight, 0n]);
+ expect(await this.mock.nonces(this.other)).to.equal(nonce + 1n);
+ });
+
+ it('supports EIP-1271 signature signatures', async function () {
+ const wallet = await ethers.deployContract('ERC1271WalletMock', [this.other]);
+ await this.token.connect(this.voter2).delegate(wallet);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+
+ // Prepare vote
+ const weight = ethers.parseEther('7') - params.decoded[0];
+ const nonce = await this.mock.nonces(this.other);
+ const data = {
+ proposalId: this.proposal.id,
+ support: VoteType.For,
+ voter: wallet.target,
+ nonce,
+ reason: 'no particular reason',
+ params: params.encoded,
+ signature: (contract, message) =>
+ getDomain(contract).then(domain => this.other.signTypedData(domain, { ExtendedBallot }, message)),
+ };
+
+ // Vote
+ await expect(this.helper.vote(data))
+ .to.emit(this.mock, 'CountParams')
+ .withArgs(...params.decoded)
+ .to.emit(this.mock, 'VoteCastWithParams')
+ .withArgs(data.voter, data.proposalId, data.support, weight, data.reason, data.params);
+
+ expect(await this.mock.proposalVotes(this.proposal.id)).to.deep.equal([0n, weight, 0n]);
+ expect(await this.mock.nonces(wallet)).to.equal(nonce + 1n);
+ });
+
+ it('reverts if signature does not match signer', async function () {
+ await this.token.connect(this.voter2).delegate(this.other);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+
+ // Prepare vote
+ const nonce = await this.mock.nonces(this.other);
+ const data = {
+ proposalId: this.proposal.id,
+ support: VoteType.For,
+ voter: this.other.address,
+ nonce,
+ reason: 'no particular reason',
+ params: params.encoded,
+ // tampered signature
+ signature: (contract, message) =>
+ getDomain(contract)
+ .then(domain => this.other.signTypedData(domain, { ExtendedBallot }, message))
+ .then(signature => {
+ const tamperedSig = ethers.toBeArray(signature);
+ tamperedSig[42] ^= 0xff;
+ return ethers.hexlify(tamperedSig);
+ }),
+ };
+
+ // Vote
+ await expect(this.helper.vote(data))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSignature')
+ .withArgs(data.voter);
+ });
+
+ it('reverts if vote nonce is incorrect', async function () {
+ await this.token.connect(this.voter2).delegate(this.other);
+
+ // Run proposal
+ await this.helper.propose();
+ await this.helper.waitForSnapshot();
+
+ // Prepare vote
+ const nonce = await this.mock.nonces(this.other);
+ const data = {
+ proposalId: this.proposal.id,
+ support: VoteType.For,
+ voter: this.other.address,
+ nonce: nonce + 1n,
+ reason: 'no particular reason',
+ params: params.encoded,
+ signature: (contract, message) =>
+ getDomain(contract).then(domain => this.other.signTypedData(domain, { ExtendedBallot }, message)),
+ };
+
+ // Vote
+ await expect(this.helper.vote(data))
+ .to.be.revertedWithCustomError(this.mock, 'GovernorInvalidSignature')
+ .withArgs(data.voter);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/ERC6372.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/ERC6372.behavior.js
new file mode 100644
index 000000000..32f27b59a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/ERC6372.behavior.js
@@ -0,0 +1,28 @@
+const { expect } = require('chai');
+const time = require('../../helpers/time');
+
+function shouldBehaveLikeERC6372(mode = 'blocknumber') {
+ describe(`ERC-6372 behavior in ${mode} mode`, function () {
+ beforeEach(async function () {
+ this.mock = this.mock ?? this.token ?? this.votes;
+ });
+
+ it('should have a correct clock value', async function () {
+ const currentClock = await this.mock.clock();
+ const expectedClock = await time.clock[mode]();
+ expect(currentClock).to.equal(expectedClock, `Clock mismatch in ${mode} mode`);
+ });
+
+ it('should have the correct CLOCK_MODE parameters', async function () {
+ const clockModeParams = new URLSearchParams(await this.mock.CLOCK_MODE());
+ const expectedFromValue = mode === 'blocknumber' ? 'default' : null;
+
+ expect(clockModeParams.get('mode')).to.equal(mode, `Expected mode to be ${mode}`);
+ expect(clockModeParams.get('from')).to.equal(expectedFromValue, `Expected 'from' to be ${expectedFromValue}`);
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeERC6372,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/Votes.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/Votes.behavior.js
new file mode 100644
index 000000000..099770132
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/Votes.behavior.js
@@ -0,0 +1,325 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getDomain, Delegation } = require('../../helpers/eip712');
+const time = require('../../helpers/time');
+
+const { shouldBehaveLikeERC6372 } = require('./ERC6372.behavior');
+
+function shouldBehaveLikeVotes(tokens, { mode = 'blocknumber', fungible = true }) {
+ beforeEach(async function () {
+ [this.delegator, this.delegatee, this.alice, this.bob, this.other] = this.accounts;
+ this.domain = await getDomain(this.votes);
+ });
+
+ shouldBehaveLikeERC6372(mode);
+
+ const getWeight = token => (fungible ? token : 1n);
+
+ describe('run votes workflow', function () {
+ it('initial nonce is 0', async function () {
+ expect(await this.votes.nonces(this.alice)).to.equal(0n);
+ });
+
+ describe('delegation with signature', function () {
+ const token = tokens[0];
+
+ it('delegation without tokens', async function () {
+ expect(await this.votes.delegates(this.alice)).to.equal(ethers.ZeroAddress);
+
+ await expect(this.votes.connect(this.alice).delegate(this.alice))
+ .to.emit(this.votes, 'DelegateChanged')
+ .withArgs(this.alice, ethers.ZeroAddress, this.alice)
+ .to.not.emit(this.votes, 'DelegateVotesChanged');
+
+ expect(await this.votes.delegates(this.alice)).to.equal(this.alice);
+ });
+
+ it('delegation with tokens', async function () {
+ await this.votes.$_mint(this.alice, token);
+ const weight = getWeight(token);
+
+ expect(await this.votes.delegates(this.alice)).to.equal(ethers.ZeroAddress);
+
+ const tx = await this.votes.connect(this.alice).delegate(this.alice);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(tx)
+ .to.emit(this.votes, 'DelegateChanged')
+ .withArgs(this.alice, ethers.ZeroAddress, this.alice)
+ .to.emit(this.votes, 'DelegateVotesChanged')
+ .withArgs(this.alice, 0n, weight);
+
+ expect(await this.votes.delegates(this.alice)).to.equal(this.alice);
+ expect(await this.votes.getVotes(this.alice)).to.equal(weight);
+ expect(await this.votes.getPastVotes(this.alice, timepoint - 1n)).to.equal(0n);
+ await mine();
+ expect(await this.votes.getPastVotes(this.alice, timepoint)).to.equal(weight);
+ });
+
+ it('delegation update', async function () {
+ await this.votes.connect(this.alice).delegate(this.alice);
+ await this.votes.$_mint(this.alice, token);
+ const weight = getWeight(token);
+
+ expect(await this.votes.delegates(this.alice)).to.equal(this.alice);
+ expect(await this.votes.getVotes(this.alice)).to.equal(weight);
+ expect(await this.votes.getVotes(this.bob)).to.equal(0);
+
+ const tx = await this.votes.connect(this.alice).delegate(this.bob);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(tx)
+ .to.emit(this.votes, 'DelegateChanged')
+ .withArgs(this.alice, this.alice, this.bob)
+ .to.emit(this.votes, 'DelegateVotesChanged')
+ .withArgs(this.alice, weight, 0)
+ .to.emit(this.votes, 'DelegateVotesChanged')
+ .withArgs(this.bob, 0, weight);
+
+ expect(await this.votes.delegates(this.alice)).to.equal(this.bob);
+ expect(await this.votes.getVotes(this.alice)).to.equal(0n);
+ expect(await this.votes.getVotes(this.bob)).to.equal(weight);
+
+ expect(await this.votes.getPastVotes(this.alice, timepoint - 1n)).to.equal(weight);
+ expect(await this.votes.getPastVotes(this.bob, timepoint - 1n)).to.equal(0n);
+ await mine();
+ expect(await this.votes.getPastVotes(this.alice, timepoint)).to.equal(0n);
+ expect(await this.votes.getPastVotes(this.bob, timepoint)).to.equal(weight);
+ });
+
+ describe('with signature', function () {
+ const nonce = 0n;
+
+ it('accept signed delegation', async function () {
+ await this.votes.$_mint(this.delegator, token);
+ const weight = getWeight(token);
+
+ const { r, s, v } = await this.delegator
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.delegatee.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ expect(await this.votes.delegates(this.delegator)).to.equal(ethers.ZeroAddress);
+
+ const tx = await this.votes.delegateBySig(this.delegatee, nonce, ethers.MaxUint256, v, r, s);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(tx)
+ .to.emit(this.votes, 'DelegateChanged')
+ .withArgs(this.delegator, ethers.ZeroAddress, this.delegatee)
+ .to.emit(this.votes, 'DelegateVotesChanged')
+ .withArgs(this.delegatee, 0, weight);
+
+ expect(await this.votes.delegates(this.delegator.address)).to.equal(this.delegatee);
+ expect(await this.votes.getVotes(this.delegator.address)).to.equal(0n);
+ expect(await this.votes.getVotes(this.delegatee)).to.equal(weight);
+ expect(await this.votes.getPastVotes(this.delegatee, timepoint - 1n)).to.equal(0n);
+ await mine();
+ expect(await this.votes.getPastVotes(this.delegatee, timepoint)).to.equal(weight);
+ });
+
+ it('rejects reused signature', async function () {
+ const { r, s, v } = await this.delegator
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.delegatee.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ await this.votes.delegateBySig(this.delegatee, nonce, ethers.MaxUint256, v, r, s);
+
+ await expect(this.votes.delegateBySig(this.delegatee, nonce, ethers.MaxUint256, v, r, s))
+ .to.be.revertedWithCustomError(this.votes, 'InvalidAccountNonce')
+ .withArgs(this.delegator, nonce + 1n);
+ });
+
+ it('rejects bad delegatee', async function () {
+ const { r, s, v } = await this.delegator
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.delegatee.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ const tx = await this.votes.delegateBySig(this.other, nonce, ethers.MaxUint256, v, r, s);
+ const receipt = await tx.wait();
+
+ const [delegateChanged] = receipt.logs.filter(
+ log => this.votes.interface.parseLog(log)?.name === 'DelegateChanged',
+ );
+ const { args } = this.votes.interface.parseLog(delegateChanged);
+ expect(args.delegator).to.not.be.equal(this.delegator);
+ expect(args.fromDelegate).to.equal(ethers.ZeroAddress);
+ expect(args.toDelegate).to.equal(this.other);
+ });
+
+ it('rejects bad nonce', async function () {
+ const { r, s, v } = await this.delegator
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.delegatee.address,
+ nonce: nonce + 1n,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ await expect(this.votes.delegateBySig(this.delegatee, nonce + 1n, ethers.MaxUint256, v, r, s))
+ .to.be.revertedWithCustomError(this.votes, 'InvalidAccountNonce')
+ .withArgs(this.delegator, 0);
+ });
+
+ it('rejects expired permit', async function () {
+ const expiry = (await time.clock.timestamp()) - 1n;
+ const { r, s, v } = await this.delegator
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.delegatee.address,
+ nonce,
+ expiry,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ await expect(this.votes.delegateBySig(this.delegatee, nonce, expiry, v, r, s))
+ .to.be.revertedWithCustomError(this.votes, 'VotesExpiredSignature')
+ .withArgs(expiry);
+ });
+ });
+ });
+
+ describe('getPastTotalSupply', function () {
+ beforeEach(async function () {
+ await this.votes.connect(this.alice).delegate(this.alice);
+ });
+
+ it('reverts if block number >= current block', async function () {
+ const timepoint = 5e10;
+ const clock = await this.votes.clock();
+ await expect(this.votes.getPastTotalSupply(timepoint))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(timepoint, clock);
+ });
+
+ it('returns 0 if there are no checkpoints', async function () {
+ expect(await this.votes.getPastTotalSupply(0n)).to.equal(0n);
+ });
+
+ it('returns the correct checkpointed total supply', async function () {
+ const weight = tokens.map(token => getWeight(token));
+
+ // t0 = mint #0
+ const t0 = await this.votes.$_mint(this.alice, tokens[0]);
+ await mine();
+ // t1 = mint #1
+ const t1 = await this.votes.$_mint(this.alice, tokens[1]);
+ await mine();
+ // t2 = burn #1
+ const t2 = await this.votes.$_burn(...(fungible ? [this.alice] : []), tokens[1]);
+ await mine();
+ // t3 = mint #2
+ const t3 = await this.votes.$_mint(this.alice, tokens[2]);
+ await mine();
+ // t4 = burn #0
+ const t4 = await this.votes.$_burn(...(fungible ? [this.alice] : []), tokens[0]);
+ await mine();
+ // t5 = burn #2
+ const t5 = await this.votes.$_burn(...(fungible ? [this.alice] : []), tokens[2]);
+ await mine();
+
+ t0.timepoint = await time.clockFromReceipt[mode](t0);
+ t1.timepoint = await time.clockFromReceipt[mode](t1);
+ t2.timepoint = await time.clockFromReceipt[mode](t2);
+ t3.timepoint = await time.clockFromReceipt[mode](t3);
+ t4.timepoint = await time.clockFromReceipt[mode](t4);
+ t5.timepoint = await time.clockFromReceipt[mode](t5);
+
+ expect(await this.votes.getPastTotalSupply(t0.timepoint - 1n)).to.equal(0);
+ expect(await this.votes.getPastTotalSupply(t0.timepoint)).to.equal(weight[0]);
+ expect(await this.votes.getPastTotalSupply(t0.timepoint + 1n)).to.equal(weight[0]);
+ expect(await this.votes.getPastTotalSupply(t1.timepoint)).to.equal(weight[0] + weight[1]);
+ expect(await this.votes.getPastTotalSupply(t1.timepoint + 1n)).to.equal(weight[0] + weight[1]);
+ expect(await this.votes.getPastTotalSupply(t2.timepoint)).to.equal(weight[0]);
+ expect(await this.votes.getPastTotalSupply(t2.timepoint + 1n)).to.equal(weight[0]);
+ expect(await this.votes.getPastTotalSupply(t3.timepoint)).to.equal(weight[0] + weight[2]);
+ expect(await this.votes.getPastTotalSupply(t3.timepoint + 1n)).to.equal(weight[0] + weight[2]);
+ expect(await this.votes.getPastTotalSupply(t4.timepoint)).to.equal(weight[2]);
+ expect(await this.votes.getPastTotalSupply(t4.timepoint + 1n)).to.equal(weight[2]);
+ expect(await this.votes.getPastTotalSupply(t5.timepoint)).to.equal(0);
+ await expect(this.votes.getPastTotalSupply(t5.timepoint + 1n))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(t5.timepoint + 1n, t5.timepoint + 1n);
+ });
+ });
+
+ // The following tests are an adaptation of
+ // https://github.com/compound-finance/compound-protocol/blob/master/tests/Governance/CompTest.js.
+ describe('Compound test suite', function () {
+ beforeEach(async function () {
+ await this.votes.$_mint(this.alice, tokens[0]);
+ await this.votes.$_mint(this.alice, tokens[1]);
+ await this.votes.$_mint(this.alice, tokens[2]);
+ });
+
+ describe('getPastVotes', function () {
+ it('reverts if block number >= current block', async function () {
+ const clock = await this.votes.clock();
+ const timepoint = 5e10; // far in the future
+ await expect(this.votes.getPastVotes(this.bob, timepoint))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(timepoint, clock);
+ });
+
+ it('returns 0 if there are no checkpoints', async function () {
+ expect(await this.votes.getPastVotes(this.bob, 0n)).to.equal(0n);
+ });
+
+ it('returns the latest block if >= last checkpoint block', async function () {
+ const delegate = await this.votes.connect(this.alice).delegate(this.bob);
+ const timepoint = await time.clockFromReceipt[mode](delegate);
+ await mine(2);
+
+ const latest = await this.votes.getVotes(this.bob);
+ expect(await this.votes.getPastVotes(this.bob, timepoint)).to.equal(latest);
+ expect(await this.votes.getPastVotes(this.bob, timepoint + 1n)).to.equal(latest);
+ });
+
+ it('returns zero if < first checkpoint block', async function () {
+ await mine();
+ const delegate = await this.votes.connect(this.alice).delegate(this.bob);
+ const timepoint = await time.clockFromReceipt[mode](delegate);
+ await mine(2);
+
+ expect(await this.votes.getPastVotes(this.bob, timepoint - 1n)).to.equal(0n);
+ });
+ });
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeVotes,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/Votes.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/Votes.test.js
new file mode 100644
index 000000000..7acacfc66
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/Votes.test.js
@@ -0,0 +1,102 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { sum } = require('../../helpers/math');
+const { zip } = require('../../helpers/iterate');
+const time = require('../../helpers/time');
+
+const { shouldBehaveLikeVotes } = require('./Votes.behavior');
+
+const MODES = {
+ blocknumber: '$VotesMock',
+ timestamp: '$VotesTimestampMock',
+};
+
+const AMOUNTS = [ethers.parseEther('10000000'), 10n, 20n];
+
+describe('Votes', function () {
+ for (const [mode, artifact] of Object.entries(MODES)) {
+ const fixture = async () => {
+ const accounts = await ethers.getSigners();
+
+ const amounts = Object.fromEntries(
+ zip(
+ accounts.slice(0, AMOUNTS.length).map(({ address }) => address),
+ AMOUNTS,
+ ),
+ );
+
+ const name = 'My Vote';
+ const version = '1';
+ const votes = await ethers.deployContract(artifact, [name, version]);
+
+ return { accounts, amounts, votes, name, version };
+ };
+
+ describe(`vote with ${mode}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeVotes(AMOUNTS, { mode, fungible: true });
+
+ it('starts with zero votes', async function () {
+ expect(await this.votes.getTotalSupply()).to.equal(0n);
+ });
+
+ describe('performs voting operations', function () {
+ beforeEach(async function () {
+ this.txs = [];
+ for (const [account, amount] of Object.entries(this.amounts)) {
+ this.txs.push(await this.votes.$_mint(account, amount));
+ }
+ });
+
+ it('reverts if block number >= current block', async function () {
+ const lastTxTimepoint = await time.clockFromReceipt[mode](this.txs.at(-1));
+ const clock = await this.votes.clock();
+ await expect(this.votes.getPastTotalSupply(lastTxTimepoint))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(lastTxTimepoint, clock);
+ });
+
+ it('delegates', async function () {
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(0n);
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(0n);
+ expect(await this.votes.delegates(this.accounts[0])).to.equal(ethers.ZeroAddress);
+ expect(await this.votes.delegates(this.accounts[1])).to.equal(ethers.ZeroAddress);
+
+ await this.votes.delegate(this.accounts[0], ethers.Typed.address(this.accounts[0]));
+
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(this.amounts[this.accounts[0].address]);
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(0n);
+ expect(await this.votes.delegates(this.accounts[0])).to.equal(this.accounts[0]);
+ expect(await this.votes.delegates(this.accounts[1])).to.equal(ethers.ZeroAddress);
+
+ await this.votes.delegate(this.accounts[1], ethers.Typed.address(this.accounts[0]));
+
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(
+ this.amounts[this.accounts[0].address] + this.amounts[this.accounts[1].address],
+ );
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(0n);
+ expect(await this.votes.delegates(this.accounts[0])).to.equal(this.accounts[0]);
+ expect(await this.votes.delegates(this.accounts[1])).to.equal(this.accounts[0]);
+ });
+
+ it('cross delegates', async function () {
+ await this.votes.delegate(this.accounts[0], ethers.Typed.address(this.accounts[1]));
+ await this.votes.delegate(this.accounts[1], ethers.Typed.address(this.accounts[0]));
+
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(this.amounts[this.accounts[1].address]);
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(this.amounts[this.accounts[0].address]);
+ });
+
+ it('returns total amount of votes', async function () {
+ const totalSupply = sum(...Object.values(this.amounts));
+ expect(await this.votes.getTotalSupply()).to.equal(totalSupply);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/VotesExtended.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/VotesExtended.test.js
new file mode 100644
index 000000000..4a66ef274
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/governance/utils/VotesExtended.test.js
@@ -0,0 +1,152 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { sum } = require('../../helpers/math');
+const { zip } = require('../../helpers/iterate');
+const time = require('../../helpers/time');
+
+const { shouldBehaveLikeVotes } = require('./Votes.behavior');
+
+const MODES = {
+ blocknumber: '$VotesExtendedMock',
+ timestamp: '$VotesExtendedTimestampMock',
+};
+
+const AMOUNTS = [ethers.parseEther('10000000'), 10n, 20n];
+
+describe('VotesExtended', function () {
+ for (const [mode, artifact] of Object.entries(MODES)) {
+ const fixture = async () => {
+ const accounts = await ethers.getSigners();
+
+ const amounts = Object.fromEntries(
+ zip(
+ accounts.slice(0, AMOUNTS.length).map(({ address }) => address),
+ AMOUNTS,
+ ),
+ );
+
+ const name = 'Override Votes';
+ const version = '1';
+ const votes = await ethers.deployContract(artifact, [name, version]);
+
+ return { accounts, amounts, votes, name, version };
+ };
+
+ describe(`vote with ${mode}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeVotes(AMOUNTS, { mode, fungible: true });
+
+ it('starts with zero votes', async function () {
+ expect(await this.votes.getTotalSupply()).to.equal(0n);
+ });
+
+ describe('performs voting operations', function () {
+ beforeEach(async function () {
+ this.txs = [];
+ for (const [account, amount] of Object.entries(this.amounts)) {
+ this.txs.push(await this.votes.$_mint(account, amount));
+ }
+ });
+
+ it('reverts if block number >= current block', async function () {
+ const lastTxTimepoint = await time.clockFromReceipt[mode](this.txs.at(-1));
+ const clock = await this.votes.clock();
+ await expect(this.votes.getPastTotalSupply(lastTxTimepoint))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(lastTxTimepoint, clock);
+ });
+
+ it('delegates', async function () {
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(0n);
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(0n);
+ expect(await this.votes.delegates(this.accounts[0])).to.equal(ethers.ZeroAddress);
+ expect(await this.votes.delegates(this.accounts[1])).to.equal(ethers.ZeroAddress);
+
+ await this.votes.delegate(this.accounts[0], ethers.Typed.address(this.accounts[0]));
+
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(this.amounts[this.accounts[0].address]);
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(0n);
+ expect(await this.votes.delegates(this.accounts[0])).to.equal(this.accounts[0]);
+ expect(await this.votes.delegates(this.accounts[1])).to.equal(ethers.ZeroAddress);
+
+ await this.votes.delegate(this.accounts[1], ethers.Typed.address(this.accounts[0]));
+
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(
+ this.amounts[this.accounts[0].address] + this.amounts[this.accounts[1].address],
+ );
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(0n);
+ expect(await this.votes.delegates(this.accounts[0])).to.equal(this.accounts[0]);
+ expect(await this.votes.delegates(this.accounts[1])).to.equal(this.accounts[0]);
+ });
+
+ it('cross delegates', async function () {
+ await this.votes.delegate(this.accounts[0], ethers.Typed.address(this.accounts[1]));
+ await this.votes.delegate(this.accounts[1], ethers.Typed.address(this.accounts[0]));
+
+ expect(await this.votes.getVotes(this.accounts[0])).to.equal(this.amounts[this.accounts[1].address]);
+ expect(await this.votes.getVotes(this.accounts[1])).to.equal(this.amounts[this.accounts[0].address]);
+ });
+
+ it('returns total amount of votes', async function () {
+ const totalSupply = sum(...Object.values(this.amounts));
+ expect(await this.votes.getTotalSupply()).to.equal(totalSupply);
+ });
+ });
+ });
+
+ describe(`checkpoint delegates with ${mode}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('checkpoint delegates', async function () {
+ const tx = await this.votes.delegate(this.accounts[0], ethers.Typed.address(this.accounts[1]));
+ const timepoint = await time.clockFromReceipt[mode](tx);
+ await mine(2);
+
+ expect(await this.votes.getPastDelegate(this.accounts[0], timepoint - 1n)).to.equal(ethers.ZeroAddress);
+ expect(await this.votes.getPastDelegate(this.accounts[0], timepoint)).to.equal(this.accounts[1].address);
+ expect(await this.votes.getPastDelegate(this.accounts[0], timepoint + 1n)).to.equal(this.accounts[1].address);
+ });
+
+ it('reverts if current timepoint <= timepoint', async function () {
+ const tx = await this.votes.delegate(this.accounts[0], ethers.Typed.address(this.accounts[1]));
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(this.votes.getPastDelegate(this.accounts[0], timepoint + 1n))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(timepoint + 1n, timepoint);
+ });
+ });
+
+ describe(`checkpoint balances with ${mode}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('checkpoint balances', async function () {
+ const tx = await this.votes.$_mint(this.accounts[0].address, 100n);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+ await mine(2);
+
+ expect(await this.votes.getPastBalanceOf(this.accounts[0].address, timepoint - 1n)).to.equal(0n);
+ expect(await this.votes.getPastBalanceOf(this.accounts[0].address, timepoint)).to.equal(100n);
+ expect(await this.votes.getPastBalanceOf(this.accounts[0].address, timepoint + 1n)).to.equal(100n);
+ });
+
+ it('reverts if current timepoint <= timepoint', async function () {
+ const tx = await this.votes.$_mint(this.accounts[0].address, 100n);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(this.votes.getPastBalanceOf(this.accounts[0], timepoint + 1n))
+ .to.be.revertedWithCustomError(this.votes, 'ERC5805FutureLookup')
+ .withArgs(timepoint + 1n, timepoint);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/access-manager.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/access-manager.js
new file mode 100644
index 000000000..3b8343059
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/access-manager.js
@@ -0,0 +1,85 @@
+const { ethers } = require('hardhat');
+
+const { MAX_UINT64 } = require('./constants');
+const time = require('./time');
+const { upgradeableSlot } = require('./storage');
+
+function buildBaseRoles() {
+ const roles = {
+ ADMIN: {
+ id: 0n,
+ },
+ SOME_ADMIN: {
+ id: 17n,
+ },
+ SOME_GUARDIAN: {
+ id: 35n,
+ },
+ SOME: {
+ id: 42n,
+ },
+ PUBLIC: {
+ id: MAX_UINT64,
+ },
+ };
+
+ // Names
+ Object.entries(roles).forEach(([name, role]) => (role.name = name));
+
+ // Defaults
+ for (const role of Object.keys(roles)) {
+ roles[role].admin = roles.ADMIN;
+ roles[role].guardian = roles.ADMIN;
+ }
+
+ // Admins
+ roles.SOME.admin = roles.SOME_ADMIN;
+
+ // Guardians
+ roles.SOME.guardian = roles.SOME_GUARDIAN;
+
+ return roles;
+}
+
+const formatAccess = access => [access[0], access[1].toString()];
+
+const MINSETBACK = time.duration.days(5);
+const EXPIRATION = time.duration.weeks(1);
+
+const EXECUTION_ID_STORAGE_SLOT = upgradeableSlot('AccessManager', 3n);
+const CONSUMING_SCHEDULE_STORAGE_SLOT = upgradeableSlot('AccessManaged', 0n);
+
+/**
+ * @requires this.{manager, caller, target, calldata}
+ */
+async function prepareOperation(manager, { caller, target, calldata, delay }) {
+ const scheduledAt = (await time.clock.timestamp()) + 1n;
+ await time.increaseTo.timestamp(scheduledAt, false); // Fix next block timestamp for predictability
+
+ return {
+ schedule: () => manager.connect(caller).schedule(target, calldata, scheduledAt + delay),
+ scheduledAt,
+ operationId: hashOperation(caller, target, calldata),
+ };
+}
+
+const lazyGetAddress = addressable => addressable.address ?? addressable.target ?? addressable;
+
+const hashOperation = (caller, target, data) =>
+ ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(
+ ['address', 'address', 'bytes'],
+ [lazyGetAddress(caller), lazyGetAddress(target), data],
+ ),
+ );
+
+module.exports = {
+ buildBaseRoles,
+ formatAccess,
+ MINSETBACK,
+ EXPIRATION,
+ EXECUTION_ID_STORAGE_SLOT,
+ CONSUMING_SCHEDULE_STORAGE_SLOT,
+ prepareOperation,
+ hashOperation,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/account.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/account.js
new file mode 100644
index 000000000..96874b16b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/account.js
@@ -0,0 +1,14 @@
+const { ethers } = require('hardhat');
+const { impersonateAccount, setBalance } = require('@nomicfoundation/hardhat-network-helpers');
+
+// Hardhat default balance
+const DEFAULT_BALANCE = 10000n * ethers.WeiPerEther;
+
+const impersonate = (account, balance = DEFAULT_BALANCE) =>
+ impersonateAccount(account)
+ .then(() => setBalance(account, balance))
+ .then(() => ethers.getSigner(account));
+
+module.exports = {
+ impersonate,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/chains.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/chains.js
new file mode 100644
index 000000000..3711a8125
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/chains.js
@@ -0,0 +1,109 @@
+// NOTE: this file defines some examples of CAIP-2 and CAIP-10 identifiers.
+// The following listing does not pretend to be exhaustive or even accurate. It SHOULD NOT be used in production.
+
+const { ethers } = require('hardhat');
+const { mapValues } = require('./iterate');
+
+// EVM (https://axelarscan.io/resources/chains?type=evm)
+const ethereum = {
+ Ethereum: '1',
+ optimism: '10',
+ binance: '56',
+ Polygon: '137',
+ Fantom: '250',
+ fraxtal: '252',
+ filecoin: '314',
+ Moonbeam: '1284',
+ centrifuge: '2031',
+ kava: '2222',
+ mantle: '5000',
+ base: '8453',
+ immutable: '13371',
+ arbitrum: '42161',
+ celo: '42220',
+ Avalanche: '43114',
+ linea: '59144',
+ blast: '81457',
+ scroll: '534352',
+ aurora: '1313161554',
+};
+
+// Cosmos (https://axelarscan.io/resources/chains?type=cosmos)
+const cosmos = {
+ Axelarnet: 'axelar-dojo-1',
+ osmosis: 'osmosis-1',
+ cosmoshub: 'cosmoshub-4',
+ juno: 'juno-1',
+ 'e-money': 'emoney-3',
+ injective: 'injective-1',
+ crescent: 'crescent-1',
+ kujira: 'kaiyo-1',
+ 'secret-snip': 'secret-4',
+ secret: 'secret-4',
+ sei: 'pacific-1',
+ stargaze: 'stargaze-1',
+ assetmantle: 'mantle-1',
+ fetch: 'fetchhub-4',
+ ki: 'kichain-2',
+ evmos: 'evmos_9001-2',
+ aura: 'xstaxy-1',
+ comdex: 'comdex-1',
+ persistence: 'core-1',
+ regen: 'regen-1',
+ umee: 'umee-1',
+ agoric: 'agoric-3',
+ xpla: 'dimension_37-1',
+ acre: 'acre_9052-1',
+ stride: 'stride-1',
+ carbon: 'carbon-1',
+ sommelier: 'sommelier-3',
+ neutron: 'neutron-1',
+ rebus: 'reb_1111-1',
+ archway: 'archway-1',
+ provenance: 'pio-mainnet-1',
+ ixo: 'ixo-5',
+ migaloo: 'migaloo-1',
+ teritori: 'teritori-1',
+ haqq: 'haqq_11235-1',
+ celestia: 'celestia',
+ ojo: 'agamotto',
+ chihuahua: 'chihuahua-1',
+ saga: 'ssc-1',
+ dymension: 'dymension_1100-1',
+ fxcore: 'fxcore',
+ c4e: 'perun-1',
+ bitsong: 'bitsong-2b',
+ nolus: 'pirin-1',
+ lava: 'lava-mainnet-1',
+ 'terra-2': 'phoenix-1',
+ terra: 'columbus-5',
+};
+
+const makeCAIP = ({ namespace, reference, account }) => ({
+ namespace,
+ reference,
+ account,
+ caip2: `${namespace}:${reference}`,
+ caip10: `${namespace}:${reference}:${account}`,
+ toCaip10: other => `${namespace}:${reference}:${ethers.getAddress(other.target ?? other.address ?? other)}`,
+});
+
+module.exports = {
+ CHAINS: mapValues(
+ Object.assign(
+ mapValues(ethereum, reference => ({
+ namespace: 'eip155',
+ reference,
+ account: ethers.Wallet.createRandom().address,
+ })),
+ mapValues(cosmos, reference => ({
+ namespace: 'cosmos',
+ reference,
+ account: ethers.encodeBase58(ethers.randomBytes(32)),
+ })),
+ ),
+ makeCAIP,
+ ),
+ getLocalCAIP: account =>
+ ethers.provider.getNetwork().then(({ chainId }) => makeCAIP({ namespace: 'eip155', reference: chainId, account })),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/constants.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/constants.js
new file mode 100644
index 000000000..4dfda5eab
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/constants.js
@@ -0,0 +1,4 @@
+module.exports = {
+ MAX_UINT48: 2n ** 48n - 1n,
+ MAX_UINT64: 2n ** 64n - 1n,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/deploy.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/deploy.js
new file mode 100644
index 000000000..0d4b9563b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/deploy.js
@@ -0,0 +1,14 @@
+const { artifacts, ethers } = require('hardhat');
+const { setCode } = require('@nomicfoundation/hardhat-network-helpers');
+const { generators } = require('./random');
+
+const forceDeployCode = (name, address = generators.address(), runner = ethers.provider) =>
+ artifacts
+ .readArtifact(name)
+ .then(({ abi, deployedBytecode }) =>
+ setCode(address, deployedBytecode).then(() => new ethers.Contract(address, abi, runner)),
+ );
+
+module.exports = {
+ forceDeployCode,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/eip712-types.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/eip712-types.js
new file mode 100644
index 000000000..d04969e44
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/eip712-types.js
@@ -0,0 +1,59 @@
+const { mapValues } = require('./iterate');
+
+const formatType = schema => Object.entries(schema).map(([name, type]) => ({ name, type }));
+
+module.exports = mapValues(
+ {
+ EIP712Domain: {
+ name: 'string',
+ version: 'string',
+ chainId: 'uint256',
+ verifyingContract: 'address',
+ salt: 'bytes32',
+ },
+ Permit: {
+ owner: 'address',
+ spender: 'address',
+ value: 'uint256',
+ nonce: 'uint256',
+ deadline: 'uint256',
+ },
+ Ballot: {
+ proposalId: 'uint256',
+ support: 'uint8',
+ voter: 'address',
+ nonce: 'uint256',
+ },
+ ExtendedBallot: {
+ proposalId: 'uint256',
+ support: 'uint8',
+ voter: 'address',
+ nonce: 'uint256',
+ reason: 'string',
+ params: 'bytes',
+ },
+ OverrideBallot: {
+ proposalId: 'uint256',
+ support: 'uint8',
+ voter: 'address',
+ nonce: 'uint256',
+ reason: 'string',
+ },
+ Delegation: {
+ delegatee: 'address',
+ nonce: 'uint256',
+ expiry: 'uint256',
+ },
+ ForwardRequest: {
+ from: 'address',
+ to: 'address',
+ value: 'uint256',
+ gas: 'uint256',
+ nonce: 'uint256',
+ deadline: 'uint48',
+ data: 'bytes',
+ },
+ },
+ formatType,
+);
+module.exports.formatType = formatType;
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/eip712.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/eip712.js
new file mode 100644
index 000000000..3843ac026
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/eip712.js
@@ -0,0 +1,45 @@
+const { ethers } = require('hardhat');
+const types = require('./eip712-types');
+
+async function getDomain(contract) {
+ const { fields, name, version, chainId, verifyingContract, salt, extensions } = await contract.eip712Domain();
+
+ if (extensions.length > 0) {
+ throw Error('Extensions not implemented');
+ }
+
+ const domain = {
+ name,
+ version,
+ chainId,
+ verifyingContract,
+ salt,
+ };
+
+ for (const [i, { name }] of types.EIP712Domain.entries()) {
+ if (!(fields & (1 << i))) {
+ delete domain[name];
+ }
+ }
+
+ return domain;
+}
+
+function domainType(domain) {
+ return types.EIP712Domain.filter(({ name }) => domain[name] !== undefined);
+}
+
+function hashTypedData(domain, structHash) {
+ return ethers.solidityPackedKeccak256(
+ ['bytes', 'bytes32', 'bytes32'],
+ ['0x1901', ethers.TypedDataEncoder.hashDomain(domain), structHash],
+ );
+}
+
+module.exports = {
+ getDomain,
+ domainType,
+ domainSeparator: ethers.TypedDataEncoder.hashDomain,
+ hashTypedData,
+ ...types,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/enums.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/enums.js
new file mode 100644
index 000000000..f95767ab7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/enums.js
@@ -0,0 +1,12 @@
+function Enum(...options) {
+ return Object.fromEntries(options.map((key, i) => [key, BigInt(i)]));
+}
+
+module.exports = {
+ Enum,
+ ProposalState: Enum('Pending', 'Active', 'Canceled', 'Defeated', 'Succeeded', 'Queued', 'Expired', 'Executed'),
+ VoteType: Object.assign(Enum('Against', 'For', 'Abstain'), { Parameters: 255n }),
+ Rounding: Enum('Floor', 'Ceil', 'Trunc', 'Expand'),
+ OperationState: Enum('Unset', 'Waiting', 'Ready', 'Done'),
+ RevertType: Enum('None', 'RevertWithoutMessage', 'RevertWithMessage', 'RevertWithCustomError', 'Panic'),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc4337-entrypoint.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc4337-entrypoint.js
new file mode 100644
index 000000000..aba49f4c4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc4337-entrypoint.js
@@ -0,0 +1,31 @@
+const { ethers } = require('hardhat');
+const { setCode } = require('@nomicfoundation/hardhat-network-helpers');
+const fs = require('fs');
+const path = require('path');
+
+const INSTANCES = {
+ entrypoint: {
+ address: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
+ abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bin/EntryPoint070.abi'), 'utf-8')),
+ bytecode: fs.readFileSync(path.resolve(__dirname, '../bin/EntryPoint070.bytecode'), 'hex'),
+ },
+ sendercreator: {
+ address: '0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C',
+ abi: JSON.parse(fs.readFileSync(path.resolve(__dirname, '../bin/SenderCreator070.abi'), 'utf-8')),
+ bytecode: fs.readFileSync(path.resolve(__dirname, '../bin/SenderCreator070.bytecode'), 'hex'),
+ },
+};
+
+function deployEntrypoint() {
+ return Promise.all(
+ Object.entries(INSTANCES).map(([name, { address, abi, bytecode }]) =>
+ setCode(address, '0x' + bytecode.replace(/0x/, ''))
+ .then(() => ethers.getContractAt(abi, address))
+ .then(instance => ({ [name]: instance })),
+ ),
+ ).then(namedInstances => Object.assign(...namedInstances));
+}
+
+module.exports = {
+ deployEntrypoint,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc4337.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc4337.js
new file mode 100644
index 000000000..50a3b4a04
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc4337.js
@@ -0,0 +1,111 @@
+const { ethers } = require('hardhat');
+
+const SIG_VALIDATION_SUCCESS = '0x0000000000000000000000000000000000000000';
+const SIG_VALIDATION_FAILURE = '0x0000000000000000000000000000000000000001';
+
+function getAddress(account) {
+ return account.target ?? account.address ?? account;
+}
+
+function pack(left, right) {
+ return ethers.solidityPacked(['uint128', 'uint128'], [left, right]);
+}
+
+function packValidationData(validAfter, validUntil, authorizer) {
+ return ethers.solidityPacked(
+ ['uint48', 'uint48', 'address'],
+ [
+ validAfter,
+ validUntil,
+ typeof authorizer == 'boolean'
+ ? authorizer
+ ? SIG_VALIDATION_SUCCESS
+ : SIG_VALIDATION_FAILURE
+ : getAddress(authorizer),
+ ],
+ );
+}
+
+function packInitCode(factory, factoryData) {
+ return ethers.solidityPacked(['address', 'bytes'], [getAddress(factory), factoryData]);
+}
+
+function packPaymasterAndData(paymaster, paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData) {
+ return ethers.solidityPacked(
+ ['address', 'uint128', 'uint128', 'bytes'],
+ [getAddress(paymaster), paymasterVerificationGasLimit, paymasterPostOpGasLimit, paymasterData],
+ );
+}
+
+/// Represent one user operation
+class UserOperation {
+ constructor(params) {
+ this.sender = getAddress(params.sender);
+ this.nonce = params.nonce;
+ this.factory = params.factory ?? undefined;
+ this.factoryData = params.factoryData ?? '0x';
+ this.callData = params.callData ?? '0x';
+ this.verificationGas = params.verificationGas ?? 10_000_000n;
+ this.callGas = params.callGas ?? 100_000n;
+ this.preVerificationGas = params.preVerificationGas ?? 100_000n;
+ this.maxPriorityFee = params.maxPriorityFee ?? 100_000n;
+ this.maxFeePerGas = params.maxFeePerGas ?? 100_000n;
+ this.paymaster = params.paymaster ?? undefined;
+ this.paymasterVerificationGasLimit = params.paymasterVerificationGasLimit ?? 0n;
+ this.paymasterPostOpGasLimit = params.paymasterPostOpGasLimit ?? 0n;
+ this.paymasterData = params.paymasterData ?? '0x';
+ this.signature = params.signature ?? '0x';
+ }
+
+ get packed() {
+ return {
+ sender: this.sender,
+ nonce: this.nonce,
+ initCode: this.factory ? packInitCode(this.factory, this.factoryData) : '0x',
+ callData: this.callData,
+ accountGasLimits: pack(this.verificationGas, this.callGas),
+ preVerificationGas: this.preVerificationGas,
+ gasFees: pack(this.maxPriorityFee, this.maxFeePerGas),
+ paymasterAndData: this.paymaster
+ ? packPaymasterAndData(
+ this.paymaster,
+ this.paymasterVerificationGasLimit,
+ this.paymasterPostOpGasLimit,
+ this.paymasterData,
+ )
+ : '0x',
+ signature: this.signature,
+ };
+ }
+
+ hash(entrypoint, chainId) {
+ const p = this.packed;
+ const h = ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(
+ ['address', 'uint256', 'bytes32', 'bytes32', 'uint256', 'uint256', 'uint256', 'uint256'],
+ [
+ p.sender,
+ p.nonce,
+ ethers.keccak256(p.initCode),
+ ethers.keccak256(p.callData),
+ p.accountGasLimits,
+ p.preVerificationGas,
+ p.gasFees,
+ ethers.keccak256(p.paymasterAndData),
+ ],
+ ),
+ );
+ return ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(['bytes32', 'address', 'uint256'], [h, getAddress(entrypoint), chainId]),
+ );
+ }
+}
+
+module.exports = {
+ SIG_VALIDATION_SUCCESS,
+ SIG_VALIDATION_FAILURE,
+ packValidationData,
+ packInitCode,
+ packPaymasterAndData,
+ UserOperation,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc7579.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc7579.js
new file mode 100644
index 000000000..6c3b4759b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/erc7579.js
@@ -0,0 +1,58 @@
+const { ethers } = require('hardhat');
+
+const MODULE_TYPE_VALIDATOR = 1;
+const MODULE_TYPE_EXECUTOR = 2;
+const MODULE_TYPE_FALLBACK = 3;
+const MODULE_TYPE_HOOK = 4;
+
+const EXEC_TYPE_DEFAULT = '0x00';
+const EXEC_TYPE_TRY = '0x01';
+
+const CALL_TYPE_CALL = '0x00';
+const CALL_TYPE_BATCH = '0x01';
+const CALL_TYPE_DELEGATE = '0xff';
+
+const encodeMode = ({
+ callType = '0x00',
+ execType = '0x00',
+ selector = '0x00000000',
+ payload = '0x00000000000000000000000000000000000000000000',
+} = {}) =>
+ ethers.solidityPacked(
+ ['bytes1', 'bytes1', 'bytes4', 'bytes4', 'bytes22'],
+ [callType, execType, '0x00000000', selector, payload],
+ );
+
+const encodeSingle = (target, value = 0n, data = '0x') =>
+ ethers.solidityPacked(['address', 'uint256', 'bytes'], [target.target ?? target.address ?? target, value, data]);
+
+const encodeBatch = (...entries) =>
+ ethers.AbiCoder.defaultAbiCoder().encode(
+ ['(address,uint256,bytes)[]'],
+ [
+ entries.map(entry =>
+ Array.isArray(entry)
+ ? [entry[0].target ?? entry[0].address ?? entry[0], entry[1] ?? 0n, entry[2] ?? '0x']
+ : [entry.target.target ?? entry.target.address ?? entry.target, entry.value ?? 0n, entry.data ?? '0x'],
+ ),
+ ],
+ );
+
+const encodeDelegate = (target, data = '0x') =>
+ ethers.solidityPacked(['address', 'bytes'], [target.target ?? target.address ?? target, data]);
+
+module.exports = {
+ MODULE_TYPE_VALIDATOR,
+ MODULE_TYPE_EXECUTOR,
+ MODULE_TYPE_FALLBACK,
+ MODULE_TYPE_HOOK,
+ EXEC_TYPE_DEFAULT,
+ EXEC_TYPE_TRY,
+ CALL_TYPE_CALL,
+ CALL_TYPE_BATCH,
+ CALL_TYPE_DELEGATE,
+ encodeMode,
+ encodeSingle,
+ encodeBatch,
+ encodeDelegate,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/governance.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/governance.js
new file mode 100644
index 000000000..540967af4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/governance.js
@@ -0,0 +1,215 @@
+const { ethers } = require('hardhat');
+const { ProposalState } = require('./enums');
+const { unique } = require('./iterate');
+const time = require('./time');
+
+const timelockSalt = (address, descriptionHash) =>
+ ethers.toBeHex((ethers.toBigInt(address) << 96n) ^ ethers.toBigInt(descriptionHash), 32);
+
+class GovernorHelper {
+ constructor(governor, mode = 'blocknumber') {
+ this.governor = governor;
+ this.mode = mode;
+ }
+
+ connect(account) {
+ this.governor = this.governor.connect(account);
+ return this;
+ }
+
+ /// Setter and getters
+ /**
+ * Specify a proposal either as
+ * 1) an array of objects [{ target, value, data }]
+ * 2) an object of arrays { targets: [], values: [], data: [] }
+ */
+ setProposal(actions, description) {
+ if (Array.isArray(actions)) {
+ this.targets = actions.map(a => a.target);
+ this.values = actions.map(a => a.value || 0n);
+ this.data = actions.map(a => a.data || '0x');
+ } else {
+ ({ targets: this.targets, values: this.values, data: this.data } = actions);
+ }
+ this.description = description;
+ return this;
+ }
+
+ get id() {
+ return ethers.keccak256(
+ ethers.AbiCoder.defaultAbiCoder().encode(['address[]', 'uint256[]', 'bytes[]', 'bytes32'], this.shortProposal),
+ );
+ }
+
+ // used for checking events
+ get signatures() {
+ return this.data.map(() => '');
+ }
+
+ get descriptionHash() {
+ return ethers.id(this.description);
+ }
+
+ // condensed version for queueing end executing
+ get shortProposal() {
+ return [this.targets, this.values, this.data, this.descriptionHash];
+ }
+
+ // full version for proposing
+ get fullProposal() {
+ return [this.targets, this.values, this.data, this.description];
+ }
+
+ get currentProposal() {
+ return this;
+ }
+
+ /// Proposal lifecycle
+ delegate(delegation) {
+ return Promise.all([
+ delegation.token.connect(delegation.to).delegate(delegation.to),
+ delegation.value === undefined ||
+ delegation.token.connect(this.governor.runner).transfer(delegation.to, delegation.value),
+ delegation.tokenId === undefined ||
+ delegation.token
+ .ownerOf(delegation.tokenId)
+ .then(owner =>
+ delegation.token.connect(this.governor.runner).transferFrom(owner, delegation.to, delegation.tokenId),
+ ),
+ ]);
+ }
+
+ propose() {
+ return this.governor.propose(...this.fullProposal);
+ }
+
+ queue() {
+ return this.governor.queue(...this.shortProposal);
+ }
+
+ execute() {
+ return this.governor.execute(...this.shortProposal);
+ }
+
+ cancel(visibility = 'external') {
+ switch (visibility) {
+ case 'external':
+ return this.governor.cancel(...this.shortProposal);
+
+ case 'internal':
+ return this.governor.$_cancel(...this.shortProposal);
+
+ default:
+ throw new Error(`unsupported visibility "${visibility}"`);
+ }
+ }
+
+ async vote(vote = {}) {
+ let method = 'castVote'; // default
+ let args = [this.id, vote.support]; // base
+
+ if (vote.signature) {
+ const sign = await vote.signature(this.governor, this.forgeMessage(vote));
+ if (vote.params || vote.reason) {
+ method = 'castVoteWithReasonAndParamsBySig';
+ args.push(vote.voter, vote.reason ?? '', vote.params ?? '0x', sign);
+ } else {
+ method = 'castVoteBySig';
+ args.push(vote.voter, sign);
+ }
+ } else if (vote.params) {
+ method = 'castVoteWithReasonAndParams';
+ args.push(vote.reason ?? '', vote.params);
+ } else if (vote.reason) {
+ method = 'castVoteWithReason';
+ args.push(vote.reason);
+ }
+
+ return await this.governor[method](...args);
+ }
+
+ async overrideVote(vote = {}) {
+ let method = 'castOverrideVote';
+ let args = [this.id, vote.support];
+
+ vote.reason = vote.reason ?? '';
+
+ if (vote.signature) {
+ let message = this.forgeMessage(vote);
+ message.reason = message.reason ?? '';
+ const sign = await vote.signature(this.governor, message);
+ method = 'castOverrideVoteBySig';
+ args.push(vote.voter, vote.reason ?? '', sign);
+ }
+
+ return await this.governor[method](...args);
+ }
+
+ /// Clock helpers
+ async waitForSnapshot(offset = 0n) {
+ const timepoint = await this.governor.proposalSnapshot(this.id);
+ return time.increaseTo[this.mode](timepoint + offset);
+ }
+
+ async waitForDeadline(offset = 0n) {
+ const timepoint = await this.governor.proposalDeadline(this.id);
+ return time.increaseTo[this.mode](timepoint + offset);
+ }
+
+ async waitForEta(offset = 0n) {
+ const timestamp = await this.governor.proposalEta(this.id);
+ return time.increaseTo.timestamp(timestamp + offset);
+ }
+
+ /// Other helpers
+ forgeMessage(vote = {}) {
+ const message = { proposalId: this.id, support: vote.support, voter: vote.voter, nonce: vote.nonce };
+
+ if (vote.params || vote.reason) {
+ message.reason = vote.reason ?? '';
+ message.params = vote.params ?? '0x';
+ }
+
+ return message;
+ }
+
+ /**
+ * Encodes a list ProposalStates into a bytes32 representation where each bit enabled corresponds to
+ * the underlying position in the `ProposalState` enum. For example:
+ *
+ * 0x000...10000
+ * ^^^^^^------ ...
+ * ^----- Succeeded
+ * ^---- Defeated
+ * ^--- Canceled
+ * ^-- Active
+ * ^- Pending
+ */
+ static proposalStatesToBitMap(proposalStates, options = {}) {
+ if (!Array.isArray(proposalStates)) {
+ proposalStates = [proposalStates];
+ }
+ const statesCount = ethers.toBigInt(Object.keys(ProposalState).length);
+ let result = 0n;
+
+ for (const state of unique(proposalStates)) {
+ if (state < 0n || state >= statesCount) {
+ expect.fail(`ProposalState ${state} out of possible states (0...${statesCount}-1)`);
+ } else {
+ result |= 1n << state;
+ }
+ }
+
+ if (options.inverted) {
+ const mask = 2n ** statesCount - 1n;
+ result = result ^ mask;
+ }
+
+ return ethers.toBeHex(result, 32);
+ }
+}
+
+module.exports = {
+ GovernorHelper,
+ timelockSalt,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/iterate.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/iterate.js
new file mode 100644
index 000000000..c7403d523
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/iterate.js
@@ -0,0 +1,36 @@
+module.exports = {
+ // ================================================= Array helpers =================================================
+
+ // Cut an array into an array of sized-length arrays
+ // Example: chunk([1,2,3,4,5,6,7,8], 3) → [[1,2,3],[4,5,6],[7,8]]
+ chunk: (array, size = 1) =>
+ Array.from({ length: Math.ceil(array.length / size) }, (_, i) => array.slice(i * size, i * size + size)),
+
+ // Cartesian cross product of an array of arrays
+ // Example: product([1,2],[a,b,c],[true]) → [[1,a,true],[1,b,true],[1,c,true],[2,a,true],[2,b,true],[2,c,true]]
+ product: (...arrays) => arrays.reduce((a, b) => a.flatMap(ai => b.map(bi => [...ai, bi])), [[]]),
+
+ // Range from start to end in increment
+ // Example: range(17,42,7) → [17,24,31,38]
+ range: (start, stop = undefined, step = 1) => {
+ if (stop == undefined) {
+ stop = start;
+ start = 0;
+ }
+ return start < stop ? Array.from({ length: (stop - start + step - 1) / step }, (_, i) => start + i * step) : [];
+ },
+
+ // Unique elements, with an optional getter function
+ // Example: unique([1,1,2,3,4,8,1,3,8,13,42]) → [1,2,3,4,8,13,42]
+ unique: (array, op = x => x) => array.filter((obj, i) => array.findIndex(entry => op(obj) === op(entry)) === i),
+
+ // Zip arrays together. If some arrays are smaller, undefined is used as a filler.
+ // Example: zip([1,2],[a,b,c],[true]) → [[1,a,true],[2,b,undefined],[undefined,c,undefined]]
+ zip: (...args) => Array.from({ length: Math.max(...args.map(arg => arg.length)) }, (_, i) => args.map(arg => arg[i])),
+
+ // ================================================ Object helpers =================================================
+
+ // Create a new object by mapping the values through a function, keeping the keys
+ // Example: mapValues({a:1,b:2,c:3}, x => x**2) → {a:1,b:4,c:9}
+ mapValues: (obj, fn) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, fn(v)])),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/math.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/math.js
new file mode 100644
index 000000000..133254aec
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/math.js
@@ -0,0 +1,33 @@
+// Array of number or bigint
+const max = (...values) => values.slice(1).reduce((x, y) => (x > y ? x : y), values.at(0));
+const min = (...values) => values.slice(1).reduce((x, y) => (x < y ? x : y), values.at(0));
+const sum = (...values) => values.slice(1).reduce((x, y) => x + y, values.at(0));
+
+// Computes modexp without BigInt overflow for large numbers
+function modExp(b, e, m) {
+ let result = 1n;
+
+ // If e is a power of two, modexp can be calculated as:
+ // for (let result = b, i = 0; i < log2(e); i++) result = modexp(result, 2, m)
+ //
+ // Given any natural number can be written in terms of powers of 2 (i.e. binary)
+ // then modexp can be calculated for any e, by multiplying b**i for all i where
+ // binary(e)[i] is 1 (i.e. a power of two).
+ for (let base = b % m; e > 0n; base = base ** 2n % m) {
+ // Least significant bit is 1
+ if (e % 2n == 1n) {
+ result = (result * base) % m;
+ }
+
+ e /= 2n; // Binary pop
+ }
+
+ return result;
+}
+
+module.exports = {
+ min,
+ max,
+ sum,
+ modExp,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/methods.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/methods.js
new file mode 100644
index 000000000..a49189720
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/methods.js
@@ -0,0 +1,14 @@
+const { ethers } = require('hardhat');
+
+const selector = signature => ethers.FunctionFragment.from(signature).selector;
+
+const interfaceId = signatures =>
+ ethers.toBeHex(
+ signatures.reduce((acc, signature) => acc ^ ethers.toBigInt(selector(signature)), 0n),
+ 4,
+ );
+
+module.exports = {
+ selector,
+ interfaceId,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/random.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/random.js
new file mode 100644
index 000000000..3adeed0a4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/random.js
@@ -0,0 +1,19 @@
+const { ethers } = require('hardhat');
+
+const generators = {
+ address: () => ethers.Wallet.createRandom().address,
+ bytes32: () => ethers.hexlify(ethers.randomBytes(32)),
+ uint256: () => ethers.toBigInt(ethers.randomBytes(32)),
+ int256: () => ethers.toBigInt(ethers.randomBytes(32)) + ethers.MinInt256,
+ hexBytes: length => ethers.hexlify(ethers.randomBytes(length)),
+};
+
+generators.address.zero = ethers.ZeroAddress;
+generators.bytes32.zero = ethers.ZeroHash;
+generators.uint256.zero = 0n;
+generators.int256.zero = 0n;
+generators.hexBytes.zero = '0x';
+
+module.exports = {
+ generators,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/storage.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/storage.js
new file mode 100644
index 000000000..466cbb10c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/storage.js
@@ -0,0 +1,48 @@
+const { ethers } = require('hardhat');
+const { setStorageAt } = require('@nomicfoundation/hardhat-network-helpers');
+
+const ImplementationLabel = 'eip1967.proxy.implementation';
+const AdminLabel = 'eip1967.proxy.admin';
+const BeaconLabel = 'eip1967.proxy.beacon';
+
+const erc1967Slot = label => ethers.toBeHex(ethers.toBigInt(ethers.id(label)) - 1n);
+const erc7201Slot = label => ethers.toBeHex(ethers.toBigInt(ethers.keccak256(erc1967Slot(label))) & ~0xffn);
+const erc7201format = contractName => `openzeppelin.storage.${contractName}`;
+
+const getSlot = (address, slot) =>
+ ethers.provider.getStorage(address, ethers.isBytesLike(slot) ? slot : erc1967Slot(slot));
+
+const setSlot = (address, slot, value) =>
+ Promise.all([
+ ethers.isAddressable(address) ? address.getAddress() : Promise.resolve(address),
+ ethers.isAddressable(value) ? value.getAddress() : Promise.resolve(value),
+ ]).then(([address, value]) => setStorageAt(address, ethers.isBytesLike(slot) ? slot : erc1967Slot(slot), value));
+
+const getAddressInSlot = (address, slot) =>
+ getSlot(address, slot).then(slotValue => ethers.AbiCoder.defaultAbiCoder().decode(['address'], slotValue)[0]);
+
+const upgradeableSlot = (contractName, offset) => {
+ try {
+ // Try to get the artifact paths, will throw if it doesn't exist
+ artifacts._getArtifactPathSync(`${contractName}Upgradeable`);
+ return offset + ethers.toBigInt(erc7201Slot(erc7201format(contractName)));
+ } catch {
+ return offset;
+ }
+};
+
+module.exports = {
+ ImplementationLabel,
+ AdminLabel,
+ BeaconLabel,
+ ImplementationSlot: erc1967Slot(ImplementationLabel),
+ AdminSlot: erc1967Slot(AdminLabel),
+ BeaconSlot: erc1967Slot(BeaconLabel),
+ erc1967Slot,
+ erc7201Slot,
+ erc7201format,
+ setSlot,
+ getSlot,
+ getAddressInSlot,
+ upgradeableSlot,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/strings.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/strings.js
new file mode 100644
index 000000000..4f34099d7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/strings.js
@@ -0,0 +1,5 @@
+module.exports = {
+ // Capitalize the first char of a string
+ // Example: capitalize('uint256') → 'Uint256'
+ capitalize: str => str.charAt(0).toUpperCase() + str.slice(1),
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/time.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/time.js
new file mode 100644
index 000000000..f6ccc3cab
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/time.js
@@ -0,0 +1,30 @@
+const { ethers } = require('hardhat');
+const { time, mine, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers');
+const { mapValues } = require('./iterate');
+
+const clock = {
+ blocknumber: () => time.latestBlock().then(ethers.toBigInt),
+ timestamp: () => time.latest().then(ethers.toBigInt),
+};
+const clockFromReceipt = {
+ blocknumber: receipt => Promise.resolve(ethers.toBigInt(receipt.blockNumber)),
+ timestamp: receipt => ethers.provider.getBlock(receipt.blockNumber).then(block => ethers.toBigInt(block.timestamp)),
+};
+const increaseBy = {
+ blockNumber: mine,
+ timestamp: (delay, mine = true) =>
+ time.latest().then(clock => increaseTo.timestamp(clock + ethers.toNumber(delay), mine)),
+};
+const increaseTo = {
+ blocknumber: mineUpTo,
+ timestamp: (to, mine = true) => (mine ? time.increaseTo(to) : time.setNextBlockTimestamp(to)),
+};
+const duration = mapValues(time.duration, fn => n => ethers.toBigInt(fn(ethers.toNumber(n))));
+
+module.exports = {
+ clock,
+ clockFromReceipt,
+ increaseBy,
+ increaseTo,
+ duration,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/txpool.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/txpool.js
new file mode 100644
index 000000000..f01327b22
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/helpers/txpool.js
@@ -0,0 +1,29 @@
+const { network } = require('hardhat');
+const { expect } = require('chai');
+const { mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { unique } = require('./iterate');
+
+async function batchInBlock(txs) {
+ try {
+ // disable auto-mining
+ await network.provider.send('evm_setAutomine', [false]);
+ // send all transactions
+ const responses = await Promise.all(txs.map(fn => fn()));
+ // mine one block
+ await mine();
+ // fetch receipts
+ const receipts = await Promise.all(responses.map(response => response.wait()));
+ // Sanity check, all tx should be in the same block
+ expect(unique(receipts.map(receipt => receipt.blockNumber))).to.have.lengthOf(1);
+ // return responses
+ return receipts;
+ } finally {
+ // enable auto-mining
+ await network.provider.send('evm_setAutomine', [true]);
+ }
+}
+
+module.exports = {
+ batchInBlock,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Context.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Context.test.js
new file mode 100644
index 000000000..15da61dad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Context.test.js
@@ -0,0 +1,133 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { impersonate } = require('../helpers/account');
+const { getDomain, ForwardRequest } = require('../helpers/eip712');
+const { MAX_UINT48 } = require('../helpers/constants');
+
+const { shouldBehaveLikeRegularContext } = require('../utils/Context.behavior');
+
+async function fixture() {
+ const [sender, other] = await ethers.getSigners();
+
+ const forwarder = await ethers.deployContract('ERC2771Forwarder', []);
+ const forwarderAsSigner = await impersonate(forwarder.target);
+ const context = await ethers.deployContract('ERC2771ContextMock', [forwarder]);
+ const domain = await getDomain(forwarder);
+ const types = { ForwardRequest };
+
+ return { sender, other, forwarder, forwarderAsSigner, context, domain, types };
+}
+
+describe('ERC2771Context', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('recognize trusted forwarder', async function () {
+ expect(await this.context.isTrustedForwarder(this.forwarder)).to.be.true;
+ });
+
+ it('returns the trusted forwarder', async function () {
+ expect(await this.context.trustedForwarder()).to.equal(this.forwarder);
+ });
+
+ describe('when called directly', function () {
+ shouldBehaveLikeRegularContext();
+ });
+
+ describe('when receiving a relayed call', function () {
+ describe('msgSender', function () {
+ it('returns the relayed transaction original sender', async function () {
+ const nonce = await this.forwarder.nonces(this.sender);
+ const data = this.context.interface.encodeFunctionData('msgSender');
+
+ const req = {
+ from: await this.sender.getAddress(),
+ to: await this.context.getAddress(),
+ value: 0n,
+ data,
+ gas: 100000n,
+ nonce,
+ deadline: MAX_UINT48,
+ };
+
+ req.signature = await this.sender.signTypedData(this.domain, this.types, req);
+
+ expect(await this.forwarder.verify(req)).to.be.true;
+
+ await expect(this.forwarder.execute(req)).to.emit(this.context, 'Sender').withArgs(this.sender);
+ });
+
+ it('returns the original sender when calldata length is less than 20 bytes (address length)', async function () {
+ // The forwarder doesn't produce calls with calldata length less than 20 bytes so `this.forwarderAsSigner` is used instead.
+ await expect(this.context.connect(this.forwarderAsSigner).msgSender())
+ .to.emit(this.context, 'Sender')
+ .withArgs(this.forwarder);
+ });
+ });
+
+ describe('msgData', function () {
+ it('returns the relayed transaction original data', async function () {
+ const args = [42n, 'OpenZeppelin'];
+
+ const nonce = await this.forwarder.nonces(this.sender);
+ const data = this.context.interface.encodeFunctionData('msgData', args);
+
+ const req = {
+ from: await this.sender.getAddress(),
+ to: await this.context.getAddress(),
+ value: 0n,
+ data,
+ gas: 100000n,
+ nonce,
+ deadline: MAX_UINT48,
+ };
+
+ req.signature = this.sender.signTypedData(this.domain, this.types, req);
+
+ expect(await this.forwarder.verify(req)).to.be.true;
+
+ await expect(this.forwarder.execute(req))
+ .to.emit(this.context, 'Data')
+ .withArgs(data, ...args);
+ });
+ });
+
+ it('returns the full original data when calldata length is less than 20 bytes (address length)', async function () {
+ const data = this.context.interface.encodeFunctionData('msgDataShort');
+
+ // The forwarder doesn't produce calls with calldata length less than 20 bytes so `this.forwarderAsSigner` is used instead.
+ await expect(await this.context.connect(this.forwarderAsSigner).msgDataShort())
+ .to.emit(this.context, 'DataShort')
+ .withArgs(data);
+ });
+ });
+
+ it('multicall poison attack', async function () {
+ const nonce = await this.forwarder.nonces(this.sender);
+ const data = this.context.interface.encodeFunctionData('multicall', [
+ [
+ // poisonned call to 'msgSender()'
+ ethers.concat([this.context.interface.encodeFunctionData('msgSender'), this.other.address]),
+ ],
+ ]);
+
+ const req = {
+ from: await this.sender.getAddress(),
+ to: await this.context.getAddress(),
+ value: 0n,
+ data,
+ gas: 100000n,
+ nonce,
+ deadline: MAX_UINT48,
+ };
+
+ req.signature = await this.sender.signTypedData(this.domain, this.types, req);
+
+ expect(await this.forwarder.verify(req)).to.be.true;
+
+ await expect(this.forwarder.execute(req)).to.emit(this.context, 'Sender').withArgs(this.sender);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.t.sol
new file mode 100644
index 000000000..e6baac6f0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.t.sol
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {ERC2771Forwarder} from "@openzeppelin/contracts/metatx/ERC2771Forwarder.sol";
+import {CallReceiverMockTrustingForwarder, CallReceiverMock} from "@openzeppelin/contracts/mocks/CallReceiverMock.sol";
+import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
+import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
+
+enum TamperType {
+ FROM,
+ TO,
+ VALUE,
+ DATA,
+ SIGNATURE
+}
+
+contract ERC2771ForwarderMock is ERC2771Forwarder {
+ constructor(string memory name) ERC2771Forwarder(name) {}
+
+ function forwardRequestStructHash(
+ ERC2771Forwarder.ForwardRequestData calldata request,
+ uint256 nonce
+ ) external view returns (bytes32) {
+ return
+ _hashTypedDataV4(
+ keccak256(
+ abi.encode(
+ _FORWARD_REQUEST_TYPEHASH,
+ request.from,
+ request.to,
+ request.value,
+ request.gas,
+ nonce,
+ request.deadline,
+ keccak256(request.data)
+ )
+ )
+ );
+ }
+}
+
+contract ERC2771ForwarderTest is Test {
+ using ECDSA for bytes32;
+
+ ERC2771ForwarderMock internal _erc2771Forwarder;
+ CallReceiverMockTrustingForwarder internal _receiver;
+
+ uint256 internal _signerPrivateKey = 0xA11CE;
+ address internal _signer = vm.addr(_signerPrivateKey);
+
+ uint256 internal constant _MAX_ETHER = 10_000_000; // To avoid overflow
+
+ function setUp() public {
+ _erc2771Forwarder = new ERC2771ForwarderMock("ERC2771Forwarder");
+ _receiver = new CallReceiverMockTrustingForwarder(address(_erc2771Forwarder));
+ }
+
+ // Forge a new ForwardRequestData
+ function _forgeRequestData() private view returns (ERC2771Forwarder.ForwardRequestData memory) {
+ return
+ _forgeRequestData({
+ value: 0,
+ deadline: uint48(block.timestamp + 1),
+ data: abi.encodeCall(CallReceiverMock.mockFunction, ())
+ });
+ }
+
+ function _forgeRequestData(
+ uint256 value,
+ uint48 deadline,
+ bytes memory data
+ ) private view returns (ERC2771Forwarder.ForwardRequestData memory) {
+ return
+ ERC2771Forwarder.ForwardRequestData({
+ from: _signer,
+ to: address(_receiver),
+ value: value,
+ gas: 30000,
+ deadline: deadline,
+ data: data,
+ signature: ""
+ });
+ }
+
+ // Sign a ForwardRequestData (in place) for a given nonce. Also returns it for convenience.
+ function _signRequestData(
+ ERC2771Forwarder.ForwardRequestData memory request,
+ uint256 nonce
+ ) private view returns (ERC2771Forwarder.ForwardRequestData memory) {
+ bytes32 digest = _erc2771Forwarder.forwardRequestStructHash(request, nonce);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPrivateKey, digest);
+ request.signature = abi.encodePacked(r, s, v);
+ return request;
+ }
+
+ // Tamper a ForwardRequestData (in place). Also returns it for convenience.
+ function _tamperRequestData(
+ ERC2771Forwarder.ForwardRequestData memory request,
+ TamperType tamper
+ ) private returns (ERC2771Forwarder.ForwardRequestData memory) {
+ if (tamper == TamperType.FROM) request.from = vm.randomAddress();
+ else if (tamper == TamperType.TO) request.to = vm.randomAddress();
+ else if (tamper == TamperType.VALUE) request.value = vm.randomUint();
+ else if (tamper == TamperType.DATA) request.data = vm.randomBytes(4);
+ else if (tamper == TamperType.SIGNATURE) request.signature = vm.randomBytes(65);
+
+ return request;
+ }
+
+ // Predict the revert error for a tampered request, and expect it is emitted.
+ function _tamperedExpectRevert(
+ ERC2771Forwarder.ForwardRequestData memory request,
+ TamperType tamper,
+ uint256 nonce
+ ) private returns (ERC2771Forwarder.ForwardRequestData memory) {
+ if (tamper == TamperType.FROM) nonce = _erc2771Forwarder.nonces(request.from);
+
+ // predict revert
+ if (tamper == TamperType.TO) {
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ ERC2771Forwarder.ERC2771UntrustfulTarget.selector,
+ request.to,
+ address(_erc2771Forwarder)
+ )
+ );
+ } else {
+ (address recovered, , ) = _erc2771Forwarder.forwardRequestStructHash(request, nonce).tryRecover(
+ request.signature
+ );
+ vm.expectRevert(
+ abi.encodeWithSelector(ERC2771Forwarder.ERC2771ForwarderInvalidSigner.selector, recovered, request.from)
+ );
+ }
+ return request;
+ }
+
+ function testExecuteAvoidsETHStuck(uint256 initialBalance, uint256 value, bool targetReverts) public {
+ initialBalance = bound(initialBalance, 0, _MAX_ETHER);
+ value = bound(value, 0, _MAX_ETHER);
+
+ // create and sign request
+ ERC2771Forwarder.ForwardRequestData memory request = _forgeRequestData({
+ value: value,
+ deadline: uint48(block.timestamp + 1),
+ data: targetReverts
+ ? abi.encodeCall(CallReceiverMock.mockFunctionRevertsNoReason, ())
+ : abi.encodeCall(CallReceiverMock.mockFunction, ())
+ });
+ _signRequestData(request, _erc2771Forwarder.nonces(_signer));
+
+ vm.deal(address(_erc2771Forwarder), initialBalance);
+ vm.deal(address(this), request.value);
+
+ if (targetReverts) vm.expectRevert();
+ _erc2771Forwarder.execute{value: value}(request);
+
+ assertEq(address(_erc2771Forwarder).balance, initialBalance);
+ }
+
+ function testExecuteBatchAvoidsETHStuck(uint256 initialBalance, uint256 batchSize, uint256 value) public {
+ uint256 seed = uint256(keccak256(abi.encodePacked(initialBalance, batchSize, value)));
+
+ batchSize = bound(batchSize, 1, 10);
+ initialBalance = bound(initialBalance, 0, _MAX_ETHER);
+ value = bound(value, 0, _MAX_ETHER);
+
+ address refundReceiver = address(0xebe);
+ uint256 refundExpected = 0;
+ uint256 nonce = _erc2771Forwarder.nonces(_signer);
+
+ // create an sign array or requests (that may fail)
+ ERC2771Forwarder.ForwardRequestData[] memory requests = new ERC2771Forwarder.ForwardRequestData[](batchSize);
+ for (uint256 i = 0; i < batchSize; ++i) {
+ bool failure = (seed >> i) & 0x1 == 0x1;
+
+ requests[i] = _forgeRequestData({
+ value: value,
+ deadline: uint48(block.timestamp + 1),
+ data: failure
+ ? abi.encodeCall(CallReceiverMock.mockFunctionRevertsNoReason, ())
+ : abi.encodeCall(CallReceiverMock.mockFunction, ())
+ });
+ _signRequestData(requests[i], nonce + i);
+
+ refundExpected += SafeCast.toUint(failure) * value;
+ }
+
+ // distribute ether
+ vm.deal(address(_erc2771Forwarder), initialBalance);
+ vm.deal(address(this), value * batchSize);
+
+ // execute batch
+ _erc2771Forwarder.executeBatch{value: value * batchSize}(requests, payable(refundReceiver));
+
+ // check balances
+ assertEq(address(_erc2771Forwarder).balance, initialBalance);
+ assertEq(refundReceiver.balance, refundExpected);
+ }
+
+ function testVerifyTamperedValues(uint8 _tamper) public {
+ TamperType tamper = _asTamper(_tamper);
+
+ // create request, sign, tamper
+ ERC2771Forwarder.ForwardRequestData memory request = _forgeRequestData();
+ _signRequestData(request, 0);
+ _tamperRequestData(request, tamper);
+
+ // should not pass verification
+ assertFalse(_erc2771Forwarder.verify(request));
+ }
+
+ function testExecuteTamperedValues(uint8 _tamper) public {
+ TamperType tamper = _asTamper(_tamper);
+
+ // create request, sign, tamper, expect execution revert
+ ERC2771Forwarder.ForwardRequestData memory request = _forgeRequestData();
+ _signRequestData(request, 0);
+ _tamperRequestData(request, tamper);
+ _tamperedExpectRevert(request, tamper, 0);
+
+ vm.deal(address(this), request.value);
+ _erc2771Forwarder.execute{value: request.value}(request);
+ }
+
+ function testExecuteBatchTamperedValuesZeroReceiver(uint8 _tamper) public {
+ TamperType tamper = _asTamper(_tamper);
+ uint256 nonce = _erc2771Forwarder.nonces(_signer);
+
+ // create an sign array or requests
+ ERC2771Forwarder.ForwardRequestData[] memory requests = new ERC2771Forwarder.ForwardRequestData[](3);
+ for (uint256 i = 0; i < requests.length; ++i) {
+ requests[i] = _forgeRequestData({
+ value: 0,
+ deadline: uint48(block.timestamp + 1),
+ data: abi.encodeCall(CallReceiverMock.mockFunction, ())
+ });
+ _signRequestData(requests[i], nonce + i);
+ }
+
+ // tamper with request[1] and expect execution revert
+ _tamperRequestData(requests[1], tamper);
+ _tamperedExpectRevert(requests[1], tamper, nonce + 1);
+
+ vm.deal(address(this), requests[1].value);
+ _erc2771Forwarder.executeBatch{value: requests[1].value}(requests, payable(address(0)));
+ }
+
+ function testExecuteBatchTamperedValues(uint8 _tamper) public {
+ TamperType tamper = _asTamper(_tamper);
+ uint256 nonce = _erc2771Forwarder.nonces(_signer);
+
+ // create an sign array or requests
+ ERC2771Forwarder.ForwardRequestData[] memory requests = new ERC2771Forwarder.ForwardRequestData[](3);
+ for (uint256 i = 0; i < requests.length; ++i) {
+ requests[i] = _forgeRequestData({
+ value: 0,
+ deadline: uint48(block.timestamp + 1),
+ data: abi.encodeCall(CallReceiverMock.mockFunction, ())
+ });
+ _signRequestData(requests[i], nonce + i);
+ }
+
+ // tamper with request[1]
+ _tamperRequestData(requests[1], tamper);
+
+ // should not revert
+ vm.expectCall(address(_receiver), abi.encodeCall(CallReceiverMock.mockFunction, ()), 1);
+
+ vm.deal(address(this), requests[1].value);
+ _erc2771Forwarder.executeBatch{value: requests[1].value}(requests, payable(address(0xebe)));
+ }
+
+ function _asTamper(uint8 _tamper) private pure returns (TamperType) {
+ return TamperType(bound(_tamper, uint8(TamperType.FROM), uint8(TamperType.SIGNATURE)));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.test.js
new file mode 100644
index 000000000..bf6cfd10c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/metatx/ERC2771Forwarder.test.js
@@ -0,0 +1,384 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getDomain, ForwardRequest } = require('../helpers/eip712');
+const { sum } = require('../helpers/math');
+const time = require('../helpers/time');
+
+async function fixture() {
+ const [sender, refundReceiver, another, ...accounts] = await ethers.getSigners();
+
+ const forwarder = await ethers.deployContract('ERC2771Forwarder', ['ERC2771Forwarder']);
+ const receiver = await ethers.deployContract('CallReceiverMockTrustingForwarder', [forwarder]);
+ const domain = await getDomain(forwarder);
+ const types = { ForwardRequest };
+
+ const forgeRequest = async (override = {}, signer = sender) => {
+ const req = {
+ from: await signer.getAddress(),
+ to: await receiver.getAddress(),
+ value: 0n,
+ data: receiver.interface.encodeFunctionData('mockFunction'),
+ gas: 100000n,
+ deadline: (await time.clock.timestamp()) + 60n,
+ nonce: await forwarder.nonces(sender),
+ ...override,
+ };
+ req.signature = await signer.signTypedData(domain, types, req);
+ return req;
+ };
+
+ const estimateRequest = request =>
+ ethers.provider.estimateGas({
+ from: forwarder,
+ to: request.to,
+ data: ethers.solidityPacked(['bytes', 'address'], [request.data, request.from]),
+ value: request.value,
+ gasLimit: request.gas,
+ });
+
+ return {
+ sender,
+ refundReceiver,
+ another,
+ accounts,
+ forwarder,
+ receiver,
+ forgeRequest,
+ estimateRequest,
+ domain,
+ types,
+ };
+}
+
+describe('ERC2771Forwarder', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('verify', function () {
+ describe('with valid signature', function () {
+ it('returns true without altering the nonce', async function () {
+ const request = await this.forgeRequest();
+ expect(await this.forwarder.nonces(request.from)).to.equal(request.nonce);
+ expect(await this.forwarder.verify(request)).to.be.true;
+ expect(await this.forwarder.nonces(request.from)).to.equal(request.nonce);
+ });
+ });
+
+ describe('with tampered values', function () {
+ it('returns false with valid signature for non-current nonce', async function () {
+ const request = await this.forgeRequest({ nonce: 1337n });
+ expect(await this.forwarder.verify(request)).to.be.false;
+ });
+
+ it('returns false with valid signature for expired deadline', async function () {
+ const request = await this.forgeRequest({ deadline: (await time.clock.timestamp()) - 1n });
+ expect(await this.forwarder.verify(request)).to.be.false;
+ });
+ });
+ });
+
+ describe('execute', function () {
+ describe('with valid requests', function () {
+ it('emits an event and consumes nonce for a successful request', async function () {
+ const request = await this.forgeRequest();
+
+ expect(await this.forwarder.nonces(request.from)).to.equal(request.nonce);
+
+ await expect(this.forwarder.execute(request))
+ .to.emit(this.receiver, 'MockFunctionCalled')
+ .to.emit(this.forwarder, 'ExecutedForwardRequest')
+ .withArgs(request.from, request.nonce, true);
+
+ expect(await this.forwarder.nonces(request.from)).to.equal(request.nonce + 1n);
+ });
+
+ it('reverts with an unsuccessful request', async function () {
+ const request = await this.forgeRequest({
+ data: this.receiver.interface.encodeFunctionData('mockFunctionRevertsNoReason'),
+ });
+
+ await expect(this.forwarder.execute(request)).to.be.revertedWithCustomError(this.forwarder, 'FailedCall');
+ });
+ });
+
+ describe('with tampered request', function () {
+ it('reverts with valid signature for non-current nonce', async function () {
+ const request = await this.forgeRequest();
+
+ // consume nonce
+ await this.forwarder.execute(request);
+
+ // nonce has changed
+ await expect(this.forwarder.execute(request))
+ .to.be.revertedWithCustomError(this.forwarder, 'ERC2771ForwarderInvalidSigner')
+ .withArgs(
+ ethers.verifyTypedData(
+ this.domain,
+ this.types,
+ { ...request, nonce: request.nonce + 1n },
+ request.signature,
+ ),
+ request.from,
+ );
+ });
+
+ it('reverts with valid signature for expired deadline', async function () {
+ const request = await this.forgeRequest({ deadline: (await time.clock.timestamp()) - 1n });
+
+ await expect(this.forwarder.execute(request))
+ .to.be.revertedWithCustomError(this.forwarder, 'ERC2771ForwarderExpiredRequest')
+ .withArgs(request.deadline);
+ });
+
+ it('reverts with valid signature but mismatched value', async function () {
+ const request = await this.forgeRequest({ value: 100n });
+
+ await expect(this.forwarder.execute(request))
+ .to.be.revertedWithCustomError(this.forwarder, 'ERC2771ForwarderMismatchedValue')
+ .withArgs(request.value, 0n);
+ });
+ });
+
+ it('bubbles out of gas', async function () {
+ const request = await this.forgeRequest({
+ data: this.receiver.interface.encodeFunctionData('mockFunctionOutOfGas'),
+ gas: 1_000_000n,
+ });
+
+ const gasLimit = 100_000n;
+ await expect(this.forwarder.execute(request, { gasLimit })).to.be.revertedWithoutReason();
+
+ const { gasUsed } = await ethers.provider
+ .getBlock('latest')
+ .then(block => block.getTransaction(0))
+ .then(tx => ethers.provider.getTransactionReceipt(tx.hash));
+
+ expect(gasUsed).to.equal(gasLimit);
+ });
+
+ it('bubbles out of gas forced by the relayer', async function () {
+ const request = await this.forgeRequest();
+
+ // If there's an incentive behind executing requests, a malicious relayer could grief
+ // the forwarder by executing requests and providing a top-level call gas limit that
+ // is too low to successfully finish the request after the 63/64 rule.
+
+ // We set the baseline to the gas limit consumed by a successful request if it was executed
+ // normally. Note this includes the 21000 buffer that also the relayer will be charged to
+ // start a request execution.
+ const estimate = await this.estimateRequest(request);
+
+ // Because the relayer call consumes gas until the `CALL` opcode, the gas left after failing
+ // the subcall won't enough to finish the top level call (after testing), so we add a
+ // moderated buffer.
+ const gasLimit = estimate + 2_000n;
+
+ // The subcall out of gas should be caught by the contract and then bubbled up consuming
+ // the available gas with an `invalid` opcode.
+ await expect(this.forwarder.execute(request, { gasLimit })).to.be.revertedWithoutReason();
+
+ const { gasUsed } = await ethers.provider
+ .getBlock('latest')
+ .then(block => block.getTransaction(0))
+ .then(tx => ethers.provider.getTransactionReceipt(tx.hash));
+
+ // We assert that indeed the gas was totally consumed.
+ expect(gasUsed).to.equal(gasLimit);
+ });
+ });
+
+ describe('executeBatch', function () {
+ const requestsValue = requests => sum(...requests.map(request => request.value));
+ const requestCount = 3;
+ const idx = 1; // index that will be tampered with
+
+ beforeEach(async function () {
+ this.forgeRequests = override =>
+ Promise.all(this.accounts.slice(0, requestCount).map(signer => this.forgeRequest(override, signer)));
+ this.requests = await this.forgeRequests({ value: 10n });
+ this.value = requestsValue(this.requests);
+ });
+
+ describe('with valid requests', function () {
+ it('sanity', async function () {
+ for (const request of this.requests) {
+ expect(await this.forwarder.verify(request)).to.be.true;
+ }
+ });
+
+ it('emits events', async function () {
+ const receipt = this.forwarder.executeBatch(this.requests, this.another, { value: this.value });
+
+ for (const request of this.requests) {
+ await expect(receipt)
+ .to.emit(this.receiver, 'MockFunctionCalled')
+ .to.emit(this.forwarder, 'ExecutedForwardRequest')
+ .withArgs(request.from, request.nonce, true);
+ }
+ });
+
+ it('increase nonces', async function () {
+ await this.forwarder.executeBatch(this.requests, this.another, { value: this.value });
+
+ for (const request of this.requests) {
+ expect(await this.forwarder.nonces(request.from)).to.equal(request.nonce + 1n);
+ }
+ });
+ });
+
+ describe('with tampered requests', function () {
+ it('reverts with mismatched value', async function () {
+ // tamper value of one of the request + resign
+ this.requests[idx] = await this.forgeRequest({ value: 100n }, this.accounts[1]);
+
+ await expect(this.forwarder.executeBatch(this.requests, this.another, { value: this.value }))
+ .to.be.revertedWithCustomError(this.forwarder, 'ERC2771ForwarderMismatchedValue')
+ .withArgs(requestsValue(this.requests), this.value);
+ });
+
+ describe('when the refund receiver is the zero address', function () {
+ beforeEach(function () {
+ this.refundReceiver = ethers.ZeroAddress;
+ });
+
+ it('reverts with at least one valid signature for non-current nonce', async function () {
+ // Execute first a request
+ await this.forwarder.execute(this.requests[idx], { value: this.requests[idx].value });
+
+ // And then fail due to an already used nonce
+ await expect(this.forwarder.executeBatch(this.requests, this.refundReceiver, { value: this.value }))
+ .to.be.revertedWithCustomError(this.forwarder, 'ERC2771ForwarderInvalidSigner')
+ .withArgs(
+ ethers.verifyTypedData(
+ this.domain,
+ this.types,
+ { ...this.requests[idx], nonce: this.requests[idx].nonce + 1n },
+ this.requests[idx].signature,
+ ),
+ this.requests[idx].from,
+ );
+ });
+
+ it('reverts with at least one valid signature for expired deadline', async function () {
+ this.requests[idx] = await this.forgeRequest(
+ { ...this.requests[idx], deadline: (await time.clock.timestamp()) - 1n },
+ this.accounts[1],
+ );
+
+ await expect(this.forwarder.executeBatch(this.requests, this.refundReceiver, { value: this.amount }))
+ .to.be.revertedWithCustomError(this.forwarder, 'ERC2771ForwarderExpiredRequest')
+ .withArgs(this.requests[idx].deadline);
+ });
+ });
+
+ describe('when the refund receiver is a known address', function () {
+ beforeEach(async function () {
+ this.initialRefundReceiverBalance = await ethers.provider.getBalance(this.refundReceiver);
+ this.initialTamperedRequestNonce = await this.forwarder.nonces(this.requests[idx].from);
+ });
+
+ it('ignores a request with a valid signature for non-current nonce', async function () {
+ // Execute first a request
+ await this.forwarder.execute(this.requests[idx], { value: this.requests[idx].value });
+ this.initialTamperedRequestNonce++; // Should be already incremented by the individual `execute`
+
+ // And then ignore the same request in a batch due to an already used nonce
+ const events = await this.forwarder
+ .executeBatch(this.requests, this.refundReceiver, { value: this.value })
+ .then(tx => tx.wait())
+ .then(receipt =>
+ receipt.logs.filter(
+ log => log?.fragment?.type == 'event' && log?.fragment?.name == 'ExecutedForwardRequest',
+ ),
+ );
+
+ expect(events).to.have.lengthOf(this.requests.length - 1);
+ });
+
+ it('ignores a request with a valid signature for expired deadline', async function () {
+ this.requests[idx] = await this.forgeRequest(
+ { ...this.requests[idx], deadline: (await time.clock.timestamp()) - 1n },
+ this.accounts[1],
+ );
+
+ const events = await this.forwarder
+ .executeBatch(this.requests, this.refundReceiver, { value: this.value })
+ .then(tx => tx.wait())
+ .then(receipt =>
+ receipt.logs.filter(
+ log => log?.fragment?.type == 'event' && log?.fragment?.name == 'ExecutedForwardRequest',
+ ),
+ );
+
+ expect(events).to.have.lengthOf(this.requests.length - 1);
+ });
+
+ afterEach(async function () {
+ // The invalid request value was refunded
+ expect(await ethers.provider.getBalance(this.refundReceiver)).to.equal(
+ this.initialRefundReceiverBalance + this.requests[idx].value,
+ );
+
+ // The invalid request from's nonce was not incremented
+ expect(await this.forwarder.nonces(this.requests[idx].from)).to.equal(this.initialTamperedRequestNonce);
+ });
+ });
+
+ it('bubbles out of gas', async function () {
+ this.requests[idx] = await this.forgeRequest({
+ data: this.receiver.interface.encodeFunctionData('mockFunctionOutOfGas'),
+ gas: 1_000_000n,
+ });
+
+ const gasLimit = 300_000n;
+ await expect(
+ this.forwarder.executeBatch(this.requests, ethers.ZeroAddress, {
+ gasLimit,
+ value: requestsValue(this.requests),
+ }),
+ ).to.be.revertedWithoutReason();
+
+ const { gasUsed } = await ethers.provider
+ .getBlock('latest')
+ .then(block => block.getTransaction(0))
+ .then(tx => ethers.provider.getTransactionReceipt(tx.hash));
+
+ expect(gasUsed).to.equal(gasLimit);
+ });
+
+ it('bubbles out of gas forced by the relayer', async function () {
+ // Similarly to the single execute, a malicious relayer could grief requests.
+
+ // We estimate until the selected request as if they were executed normally
+ const estimate = await Promise.all(this.requests.slice(0, idx + 1).map(this.estimateRequest)).then(gas =>
+ sum(...gas),
+ );
+
+ // We add a Buffer to account for all the gas that's used before the selected call.
+ // Note is slightly bigger because the selected request is not the index 0 and it affects
+ // the buffer needed.
+ const gasLimit = estimate + 10_000n;
+
+ // The subcall out of gas should be caught by the contract and then bubbled up consuming
+ // the available gas with an `invalid` opcode.
+ await expect(
+ this.forwarder.executeBatch(this.requests, ethers.ZeroAddress, {
+ gasLimit,
+ value: requestsValue(this.requests),
+ }),
+ ).to.be.revertedWithoutReason();
+
+ const { gasUsed } = await ethers.provider
+ .getBlock('latest')
+ .then(block => block.getTransaction(0))
+ .then(tx => ethers.provider.getTransactionReceipt(tx.hash));
+
+ // We assert that indeed the gas was totally consumed.
+ expect(gasUsed).to.equal(gasLimit);
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.behaviour.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.behaviour.js
new file mode 100644
index 000000000..dcc620665
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.behaviour.js
@@ -0,0 +1,160 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+module.exports = function shouldBehaveLikeClone() {
+ const assertProxyInitialization = function ({ value, balance }) {
+ it('initializes the proxy', async function () {
+ const dummy = await ethers.getContractAt('DummyImplementation', this.proxy);
+ expect(await dummy.value()).to.equal(value);
+ });
+
+ it('has expected balance', async function () {
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(balance);
+ });
+ };
+
+ describe('construct with value', function () {
+ const value = 10n;
+
+ it('factory has enough balance', async function () {
+ await this.deployer.sendTransaction({ to: this.factory, value });
+
+ const instance = await this.createClone({ deployValue: value });
+ await expect(instance.deploymentTransaction()).to.changeEtherBalances([this.factory, instance], [-value, value]);
+
+ expect(await ethers.provider.getBalance(instance)).to.equal(value);
+ });
+
+ it('factory does not have enough balance', async function () {
+ await expect(this.createClone({ deployValue: value }))
+ .to.be.revertedWithCustomError(this.factory, 'InsufficientBalance')
+ .withArgs(0n, value);
+ });
+ });
+
+ describe('initialization without parameters', function () {
+ describe('non payable', function () {
+ const expectedInitializedValue = 10n;
+
+ beforeEach(async function () {
+ this.initializeData = await this.implementation.interface.encodeFunctionData('initializeNonPayable');
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createClone({ initData: this.initializeData });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 6n;
+
+ it('reverts', async function () {
+ await expect(this.createClone({ initData: this.initializeData, initValue: value })).to.be.reverted;
+ });
+ });
+ });
+
+ describe('payable', function () {
+ const expectedInitializedValue = 100n;
+
+ beforeEach(async function () {
+ this.initializeData = await this.implementation.interface.encodeFunctionData('initializePayable');
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createClone({ initData: this.initializeData });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 6n;
+
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createClone({ initData: this.initializeData, initValue: value });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: value,
+ });
+ });
+ });
+ });
+
+ describe('initialization with parameters', function () {
+ describe('non payable', function () {
+ const expectedInitializedValue = 10n;
+
+ beforeEach(async function () {
+ this.initializeData = await this.implementation.interface.encodeFunctionData('initializeNonPayableWithValue', [
+ expectedInitializedValue,
+ ]);
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createClone({ initData: this.initializeData });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 6n;
+
+ it('reverts', async function () {
+ await expect(this.createClone({ initData: this.initializeData, initValue: value })).to.be.reverted;
+ });
+ });
+ });
+
+ describe('payable', function () {
+ const expectedInitializedValue = 42n;
+
+ beforeEach(function () {
+ this.initializeData = this.implementation.interface.encodeFunctionData('initializePayableWithValue', [
+ expectedInitializedValue,
+ ]);
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createClone({ initData: this.initializeData });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 6n;
+
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createClone({ initData: this.initializeData, initValue: value });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: value,
+ });
+ });
+ });
+ });
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.t.sol
new file mode 100644
index 000000000..e589ba906
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.t.sol
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
+
+contract ClonesTest is Test {
+ function getNumber() external pure returns (uint256) {
+ return 42;
+ }
+
+ function testSymbolicPredictDeterministicAddressSpillage(address implementation, bytes32 salt) public {
+ address predicted = Clones.predictDeterministicAddress(implementation, salt);
+ bytes32 spillage;
+ assembly ("memory-safe") {
+ spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
+ }
+ assertEq(spillage, bytes32(0));
+ }
+
+ function testSymbolicPredictDeterministicAddressWithImmutableArgsSpillage(
+ address implementation,
+ bytes32 salt,
+ bytes memory args
+ ) public {
+ vm.assume(args.length < 0xbfd3);
+
+ address predicted = Clones.predictDeterministicAddressWithImmutableArgs(implementation, args, salt);
+ bytes32 spillage;
+ /// @solidity memory-safe-assembly
+ assembly {
+ spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
+ }
+ assertEq(spillage, bytes32(0));
+ }
+
+ function testCloneDirty() external {
+ address cloneClean = Clones.clone(address(this));
+ address cloneDirty = Clones.clone(_dirty(address(this)));
+
+ // both clones have the same code
+ assertEq(cloneClean.code, cloneDirty.code);
+
+ // both clones behave as expected
+ assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
+ assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
+ }
+
+ function testCloneDeterministicDirty(bytes32 salt) external {
+ address cloneClean = Clones.cloneDeterministic(address(this), salt);
+ address cloneDirty = Clones.cloneDeterministic(_dirty(address(this)), ~salt);
+
+ // both clones have the same code
+ assertEq(cloneClean.code, cloneDirty.code);
+
+ // both clones behave as expected
+ assertEq(ClonesTest(cloneClean).getNumber(), this.getNumber());
+ assertEq(ClonesTest(cloneDirty).getNumber(), this.getNumber());
+ }
+
+ function testPredictDeterministicAddressDirty(bytes32 salt) external {
+ address predictClean = Clones.predictDeterministicAddress(address(this), salt);
+ address predictDirty = Clones.predictDeterministicAddress(_dirty(address(this)), salt);
+
+ //prediction should be similar
+ assertEq(predictClean, predictDirty);
+ }
+
+ function testFetchCloneArgs(bytes memory args, bytes32 salt) external {
+ vm.assume(args.length < 0xbfd3);
+
+ address instance1 = Clones.cloneWithImmutableArgs(address(this), args);
+ address instance2 = Clones.cloneDeterministicWithImmutableArgs(address(this), args, salt);
+
+ // both clones have the same code
+ assertEq(instance1.code, instance2.code);
+
+ // both clones behave as expected and args can be fetched
+ assertEq(ClonesTest(instance1).getNumber(), this.getNumber());
+ assertEq(ClonesTest(instance2).getNumber(), this.getNumber());
+ assertEq(Clones.fetchCloneArgs(instance1), args);
+ assertEq(Clones.fetchCloneArgs(instance2), args);
+ }
+
+ function _dirty(address input) private pure returns (address output) {
+ assembly ("memory-safe") {
+ output := or(input, shl(160, not(0)))
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.test.js
new file mode 100644
index 000000000..0706c6f83
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Clones.test.js
@@ -0,0 +1,175 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { generators } = require('../helpers/random');
+
+const shouldBehaveLikeClone = require('./Clones.behaviour');
+
+const cloneInitCode = (instance, args = undefined) =>
+ args
+ ? ethers.concat([
+ '0x61',
+ ethers.toBeHex(0x2d + ethers.getBytes(args).length, 2),
+ '0x3d81600a3d39f3363d3d373d3d3d363d73',
+ instance.target ?? instance.address ?? instance,
+ '0x5af43d82803e903d91602b57fd5bf3',
+ args,
+ ])
+ : ethers.concat([
+ '0x3d602d80600a3d3981f3363d3d373d3d3d363d73',
+ instance.target ?? instance.address ?? instance,
+ '0x5af43d82803e903d91602b57fd5bf3',
+ ]);
+
+async function fixture() {
+ const [deployer] = await ethers.getSigners();
+
+ const factory = await ethers.deployContract('$Clones');
+ const implementation = await ethers.deployContract('DummyImplementation');
+
+ const newClone =
+ args =>
+ async (opts = {}) => {
+ const clone = await (args
+ ? factory.$cloneWithImmutableArgs.staticCall(implementation, args)
+ : factory.$clone.staticCall(implementation)
+ ).then(address => implementation.attach(address));
+ const tx = await (args
+ ? opts.deployValue
+ ? factory.$cloneWithImmutableArgs(implementation, args, ethers.Typed.uint256(opts.deployValue))
+ : factory.$cloneWithImmutableArgs(implementation, args)
+ : opts.deployValue
+ ? factory.$clone(implementation, ethers.Typed.uint256(opts.deployValue))
+ : factory.$clone(implementation));
+ if (opts.initData || opts.initValue) {
+ await deployer.sendTransaction({ to: clone, value: opts.initValue ?? 0n, data: opts.initData ?? '0x' });
+ }
+ return Object.assign(clone, { deploymentTransaction: () => tx });
+ };
+
+ const newCloneDeterministic =
+ args =>
+ async (opts = {}) => {
+ const salt = opts.salt ?? ethers.randomBytes(32);
+ const clone = await (args
+ ? factory.$cloneDeterministicWithImmutableArgs.staticCall(implementation, args, salt)
+ : factory.$cloneDeterministic.staticCall(implementation, salt)
+ ).then(address => implementation.attach(address));
+ const tx = await (args
+ ? opts.deployValue
+ ? factory.$cloneDeterministicWithImmutableArgs(
+ implementation,
+ args,
+ salt,
+ ethers.Typed.uint256(opts.deployValue),
+ )
+ : factory.$cloneDeterministicWithImmutableArgs(implementation, args, salt)
+ : opts.deployValue
+ ? factory.$cloneDeterministic(implementation, salt, ethers.Typed.uint256(opts.deployValue))
+ : factory.$cloneDeterministic(implementation, salt));
+ if (opts.initData || opts.initValue) {
+ await deployer.sendTransaction({ to: clone, value: opts.initValue ?? 0n, data: opts.initData ?? '0x' });
+ }
+ return Object.assign(clone, { deploymentTransaction: () => tx });
+ };
+
+ return { deployer, factory, implementation, newClone, newCloneDeterministic };
+}
+
+describe('Clones', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const args of [undefined, '0x', '0x11223344']) {
+ describe(args ? `with immutable args: ${args}` : 'without immutable args', function () {
+ describe('clone', function () {
+ beforeEach(async function () {
+ this.createClone = this.newClone(args);
+ });
+
+ shouldBehaveLikeClone();
+
+ it('get immutable arguments', async function () {
+ const instance = await this.createClone();
+ expect(await this.factory.$fetchCloneArgs(instance)).to.equal(args ?? '0x');
+ });
+ });
+
+ describe('cloneDeterministic', function () {
+ beforeEach(async function () {
+ this.createClone = this.newCloneDeterministic(args);
+ });
+
+ shouldBehaveLikeClone();
+
+ it('get immutable arguments', async function () {
+ const instance = await this.createClone();
+ expect(await this.factory.$fetchCloneArgs(instance)).to.equal(args ?? '0x');
+ });
+
+ it('revert if address already used', async function () {
+ const salt = ethers.randomBytes(32);
+
+ const deployClone = () =>
+ args
+ ? this.factory.$cloneDeterministicWithImmutableArgs(this.implementation, args, salt)
+ : this.factory.$cloneDeterministic(this.implementation, salt);
+
+ // deploy once
+ await expect(deployClone()).to.not.be.reverted;
+
+ // deploy twice
+ await expect(deployClone()).to.be.revertedWithCustomError(this.factory, 'FailedDeployment');
+ });
+
+ it('address prediction', async function () {
+ const salt = ethers.randomBytes(32);
+
+ const expected = ethers.getCreate2Address(
+ this.factory.target,
+ salt,
+ ethers.keccak256(cloneInitCode(this.implementation, args)),
+ );
+
+ if (args) {
+ const predicted = await this.factory.$predictDeterministicAddressWithImmutableArgs(
+ this.implementation,
+ args,
+ salt,
+ );
+ expect(predicted).to.equal(expected);
+
+ await expect(this.factory.$cloneDeterministicWithImmutableArgs(this.implementation, args, salt))
+ .to.emit(this.factory, 'return$cloneDeterministicWithImmutableArgs_address_bytes_bytes32')
+ .withArgs(predicted);
+ } else {
+ const predicted = await this.factory.$predictDeterministicAddress(this.implementation, salt);
+ expect(predicted).to.equal(expected);
+
+ await expect(this.factory.$cloneDeterministic(this.implementation, salt))
+ .to.emit(this.factory, 'return$cloneDeterministic_address_bytes32')
+ .withArgs(predicted);
+ }
+ });
+ });
+ });
+ }
+
+ it('EIP-170 limit on immutable args', async function () {
+ // EIP-170 limits the contract code size to 0x6000
+ // This limits the length of immutable args to 0x5fd3
+ const args = generators.hexBytes(0x5fd4);
+ const salt = ethers.randomBytes(32);
+
+ await expect(
+ this.factory.$predictDeterministicAddressWithImmutableArgs(this.implementation, args, salt),
+ ).to.be.revertedWithCustomError(this.factory, 'CloneArgumentsTooLong');
+
+ await expect(this.factory.$cloneWithImmutableArgs(this.implementation, args)).to.be.revertedWithCustomError(
+ this.factory,
+ 'CloneArgumentsTooLong',
+ );
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Proxy.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Proxy.test.js
new file mode 100644
index 000000000..b22280046
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Proxy.test.js
@@ -0,0 +1,23 @@
+const { ethers } = require('hardhat');
+
+const shouldBehaveLikeProxy = require('../Proxy.behaviour');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const fixture = async () => {
+ const [nonContractAddress] = await ethers.getSigners();
+
+ const implementation = await ethers.deployContract('DummyImplementation');
+
+ const createProxy = (implementation, initData, opts) =>
+ ethers.deployContract('ERC1967Proxy', [implementation, initData], opts);
+
+ return { nonContractAddress, implementation, createProxy };
+};
+
+describe('ERC1967Proxy', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeProxy();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Utils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Utils.test.js
new file mode 100644
index 000000000..089032498
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/ERC1967/ERC1967Utils.test.js
@@ -0,0 +1,162 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getAddressInSlot, setSlot, ImplementationSlot, AdminSlot, BeaconSlot } = require('../../helpers/storage');
+
+async function fixture() {
+ const [, admin, anotherAccount] = await ethers.getSigners();
+
+ const utils = await ethers.deployContract('$ERC1967Utils');
+ const v1 = await ethers.deployContract('DummyImplementation');
+ const v2 = await ethers.deployContract('CallReceiverMock');
+
+ return { admin, anotherAccount, utils, v1, v2 };
+}
+
+describe('ERC1967Utils', function () {
+ beforeEach('setup', async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('IMPLEMENTATION_SLOT', function () {
+ beforeEach('set v1 implementation', async function () {
+ await setSlot(this.utils, ImplementationSlot, this.v1);
+ });
+
+ describe('getImplementation', function () {
+ it('returns current implementation and matches implementation slot value', async function () {
+ expect(await this.utils.$getImplementation()).to.equal(this.v1);
+ expect(await getAddressInSlot(this.utils, ImplementationSlot)).to.equal(this.v1);
+ });
+ });
+
+ describe('upgradeToAndCall', function () {
+ it('sets implementation in storage and emits event', async function () {
+ const newImplementation = this.v2;
+ const tx = await this.utils.$upgradeToAndCall(newImplementation, '0x');
+
+ expect(await getAddressInSlot(this.utils, ImplementationSlot)).to.equal(newImplementation);
+ await expect(tx).to.emit(this.utils, 'Upgraded').withArgs(newImplementation);
+ });
+
+ it('reverts when implementation does not contain code', async function () {
+ await expect(this.utils.$upgradeToAndCall(this.anotherAccount, '0x'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidImplementation')
+ .withArgs(this.anotherAccount);
+ });
+
+ describe('when data is empty', function () {
+ it('reverts when value is sent', async function () {
+ await expect(this.utils.$upgradeToAndCall(this.v2, '0x', { value: 1 })).to.be.revertedWithCustomError(
+ this.utils,
+ 'ERC1967NonPayable',
+ );
+ });
+ });
+
+ describe('when data is not empty', function () {
+ it('delegates a call to the new implementation', async function () {
+ const initializeData = this.v2.interface.encodeFunctionData('mockFunction');
+ const tx = await this.utils.$upgradeToAndCall(this.v2, initializeData);
+ await expect(tx).to.emit(await ethers.getContractAt('CallReceiverMock', this.utils), 'MockFunctionCalled');
+ });
+ });
+ });
+ });
+
+ describe('ADMIN_SLOT', function () {
+ beforeEach('set admin', async function () {
+ await setSlot(this.utils, AdminSlot, this.admin);
+ });
+
+ describe('getAdmin', function () {
+ it('returns current admin and matches admin slot value', async function () {
+ expect(await this.utils.$getAdmin()).to.equal(this.admin);
+ expect(await getAddressInSlot(this.utils, AdminSlot)).to.equal(this.admin);
+ });
+ });
+
+ describe('changeAdmin', function () {
+ it('sets admin in storage and emits event', async function () {
+ const newAdmin = this.anotherAccount;
+ const tx = await this.utils.$changeAdmin(newAdmin);
+
+ expect(await getAddressInSlot(this.utils, AdminSlot)).to.equal(newAdmin);
+ await expect(tx).to.emit(this.utils, 'AdminChanged').withArgs(this.admin, newAdmin);
+ });
+
+ it('reverts when setting the address zero as admin', async function () {
+ await expect(this.utils.$changeAdmin(ethers.ZeroAddress))
+ .to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidAdmin')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+ });
+
+ describe('BEACON_SLOT', function () {
+ beforeEach('set beacon', async function () {
+ this.beacon = await ethers.deployContract('UpgradeableBeaconMock', [this.v1]);
+ await setSlot(this.utils, BeaconSlot, this.beacon);
+ });
+
+ describe('getBeacon', function () {
+ it('returns current beacon and matches beacon slot value', async function () {
+ expect(await this.utils.$getBeacon()).to.equal(this.beacon);
+ expect(await getAddressInSlot(this.utils, BeaconSlot)).to.equal(this.beacon);
+ });
+ });
+
+ describe('upgradeBeaconToAndCall', function () {
+ it('sets beacon in storage and emits event', async function () {
+ const newBeacon = await ethers.deployContract('UpgradeableBeaconMock', [this.v2]);
+ const tx = await this.utils.$upgradeBeaconToAndCall(newBeacon, '0x');
+
+ expect(await getAddressInSlot(this.utils, BeaconSlot)).to.equal(newBeacon);
+ await expect(tx).to.emit(this.utils, 'BeaconUpgraded').withArgs(newBeacon);
+ });
+
+ it('reverts when beacon does not contain code', async function () {
+ await expect(this.utils.$upgradeBeaconToAndCall(this.anotherAccount, '0x'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidBeacon')
+ .withArgs(this.anotherAccount);
+ });
+
+ it("reverts when beacon's implementation does not contain code", async function () {
+ const newBeacon = await ethers.deployContract('UpgradeableBeaconMock', [this.anotherAccount]);
+
+ await expect(this.utils.$upgradeBeaconToAndCall(newBeacon, '0x'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC1967InvalidImplementation')
+ .withArgs(this.anotherAccount);
+ });
+
+ describe('when data is empty', function () {
+ it('reverts when value is sent', async function () {
+ const newBeacon = await ethers.deployContract('UpgradeableBeaconMock', [this.v2]);
+ await expect(this.utils.$upgradeBeaconToAndCall(newBeacon, '0x', { value: 1 })).to.be.revertedWithCustomError(
+ this.utils,
+ 'ERC1967NonPayable',
+ );
+ });
+ });
+
+ describe('when data is not empty', function () {
+ it('delegates a call to the new implementation', async function () {
+ const initializeData = this.v2.interface.encodeFunctionData('mockFunction');
+ const newBeacon = await ethers.deployContract('UpgradeableBeaconMock', [this.v2]);
+ const tx = await this.utils.$upgradeBeaconToAndCall(newBeacon, initializeData);
+ await expect(tx).to.emit(await ethers.getContractAt('CallReceiverMock', this.utils), 'MockFunctionCalled');
+ });
+ });
+
+ describe('reentrant beacon implementation() call', function () {
+ it('sees the new beacon implementation', async function () {
+ const newBeacon = await ethers.deployContract('UpgradeableBeaconReentrantMock');
+ await expect(this.utils.$upgradeBeaconToAndCall(newBeacon, '0x'))
+ .to.be.revertedWithCustomError(newBeacon, 'BeaconProxyBeaconSlotAddress')
+ .withArgs(newBeacon);
+ });
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Proxy.behaviour.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Proxy.behaviour.js
new file mode 100644
index 000000000..f459c0926
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/Proxy.behaviour.js
@@ -0,0 +1,185 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+const { getAddressInSlot, ImplementationSlot } = require('../helpers/storage');
+
+module.exports = function shouldBehaveLikeProxy() {
+ it('cannot be initialized with a non-contract address', async function () {
+ const initializeData = '0x';
+ const contractFactory = await ethers.getContractFactory('ERC1967Proxy');
+ await expect(this.createProxy(this.nonContractAddress, initializeData))
+ .to.be.revertedWithCustomError(contractFactory, 'ERC1967InvalidImplementation')
+ .withArgs(this.nonContractAddress);
+ });
+
+ const assertProxyInitialization = function ({ value, balance }) {
+ it('sets the implementation address', async function () {
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.implementation);
+ });
+
+ it('initializes the proxy', async function () {
+ const dummy = this.implementation.attach(this.proxy);
+ expect(await dummy.value()).to.equal(value);
+ });
+
+ it('has expected balance', async function () {
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(balance);
+ });
+ };
+
+ describe('without initialization', function () {
+ const initializeData = '0x';
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, initializeData);
+ });
+
+ assertProxyInitialization({ value: 0n, balance: 0n });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 5n;
+
+ it('reverts', async function () {
+ await expect(this.createProxy(this.implementation, initializeData, { value })).to.be.reverted;
+ });
+ });
+ });
+
+ describe('initialization without parameters', function () {
+ describe('non payable', function () {
+ const expectedInitializedValue = 10n;
+
+ beforeEach(function () {
+ this.initializeData = this.implementation.interface.encodeFunctionData('initializeNonPayable');
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, this.initializeData);
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0n,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 5n;
+
+ it('reverts', async function () {
+ await expect(this.createProxy(this.implementation, this.initializeData, { value })).to.be.reverted;
+ });
+ });
+ });
+
+ describe('payable', function () {
+ const expectedInitializedValue = 100n;
+
+ beforeEach(function () {
+ this.initializeData = this.implementation.interface.encodeFunctionData('initializePayable');
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, this.initializeData);
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0n,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10e5;
+
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, this.initializeData, { value });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: value,
+ });
+ });
+ });
+ });
+
+ describe('initialization with parameters', function () {
+ describe('non payable', function () {
+ const expectedInitializedValue = 10n;
+
+ beforeEach(function () {
+ this.initializeData = this.implementation.interface.encodeFunctionData('initializeNonPayableWithValue', [
+ expectedInitializedValue,
+ ]);
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, this.initializeData);
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10e5;
+
+ it('reverts', async function () {
+ await expect(this.createProxy(this.implementation, this.initializeData, { value })).to.be.reverted;
+ });
+ });
+ });
+
+ describe('payable', function () {
+ const expectedInitializedValue = 42n;
+
+ beforeEach(function () {
+ this.initializeData = this.implementation.interface.encodeFunctionData('initializePayableWithValue', [
+ expectedInitializedValue,
+ ]);
+ });
+
+ describe('when not sending balance', function () {
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, this.initializeData);
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: 0n,
+ });
+ });
+
+ describe('when sending some balance', function () {
+ const value = 10n ** 5n;
+
+ beforeEach('creating proxy', async function () {
+ this.proxy = await this.createProxy(this.implementation, this.initializeData, { value });
+ });
+
+ assertProxyInitialization({
+ value: expectedInitializedValue,
+ balance: value,
+ });
+ });
+ });
+
+ describe('reverting initialization', function () {
+ beforeEach(function () {
+ this.initializeData = this.implementation.interface.encodeFunctionData('reverts');
+ });
+
+ it('reverts', async function () {
+ await expect(this.createProxy(this.implementation, this.initializeData)).to.be.reverted;
+ });
+ });
+ });
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/beacon/BeaconProxy.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/beacon/BeaconProxy.test.js
new file mode 100644
index 000000000..0a0878446
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/beacon/BeaconProxy.test.js
@@ -0,0 +1,141 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getAddressInSlot, BeaconSlot } = require('../../helpers/storage');
+
+async function fixture() {
+ const [admin, other] = await ethers.getSigners();
+
+ const v1 = await ethers.deployContract('DummyImplementation');
+ const v2 = await ethers.deployContract('DummyImplementationV2');
+ const factory = await ethers.getContractFactory('BeaconProxy');
+ const beacon = await ethers.deployContract('UpgradeableBeacon', [v1, admin]);
+
+ const newBeaconProxy = (beacon, data, opts = {}) => factory.deploy(beacon, data, opts);
+
+ return { admin, other, factory, beacon, v1, v2, newBeaconProxy };
+}
+
+describe('BeaconProxy', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('bad beacon is not accepted', function () {
+ it('non-contract beacon', async function () {
+ const notBeacon = this.other;
+
+ await expect(this.newBeaconProxy(notBeacon, '0x'))
+ .to.be.revertedWithCustomError(this.factory, 'ERC1967InvalidBeacon')
+ .withArgs(notBeacon);
+ });
+
+ it('non-compliant beacon', async function () {
+ const badBeacon = await ethers.deployContract('BadBeaconNoImpl');
+
+ // BadBeaconNoImpl does not provide `implementation()` has no fallback.
+ // This causes ERC1967Utils._setBeacon to revert.
+ await expect(this.newBeaconProxy(badBeacon, '0x')).to.be.revertedWithoutReason();
+ });
+
+ it('non-contract implementation', async function () {
+ const badBeacon = await ethers.deployContract('BadBeaconNotContract');
+
+ await expect(this.newBeaconProxy(badBeacon, '0x'))
+ .to.be.revertedWithCustomError(this.factory, 'ERC1967InvalidImplementation')
+ .withArgs(await badBeacon.implementation());
+ });
+ });
+
+ describe('initialization', function () {
+ async function assertInitialized({ value, balance }) {
+ const beaconAddress = await getAddressInSlot(this.proxy, BeaconSlot);
+ expect(beaconAddress).to.equal(this.beacon);
+
+ const dummy = this.v1.attach(this.proxy);
+ expect(await dummy.value()).to.equal(value);
+
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(balance);
+ }
+
+ it('no initialization', async function () {
+ this.proxy = await this.newBeaconProxy(this.beacon, '0x');
+ await assertInitialized.bind(this)({ value: 0n, balance: 0n });
+ });
+
+ it('non-payable initialization', async function () {
+ const value = 55n;
+ const data = this.v1.interface.encodeFunctionData('initializeNonPayableWithValue', [value]);
+
+ this.proxy = await this.newBeaconProxy(this.beacon, data);
+ await assertInitialized.bind(this)({ value, balance: 0n });
+ });
+
+ it('payable initialization', async function () {
+ const value = 55n;
+ const data = this.v1.interface.encodeFunctionData('initializePayableWithValue', [value]);
+ const balance = 100n;
+
+ this.proxy = await this.newBeaconProxy(this.beacon, data, { value: balance });
+ await assertInitialized.bind(this)({ value, balance });
+ });
+
+ it('reverting initialization due to value', async function () {
+ await expect(this.newBeaconProxy(this.beacon, '0x', { value: 1n })).to.be.revertedWithCustomError(
+ this.factory,
+ 'ERC1967NonPayable',
+ );
+ });
+
+ it('reverting initialization function', async function () {
+ const data = this.v1.interface.encodeFunctionData('reverts');
+ await expect(this.newBeaconProxy(this.beacon, data)).to.be.revertedWith('DummyImplementation reverted');
+ });
+ });
+
+ describe('upgrade', function () {
+ it('upgrade a proxy by upgrading its beacon', async function () {
+ const value = 10n;
+ const data = this.v1.interface.encodeFunctionData('initializeNonPayableWithValue', [value]);
+ const proxy = await this.newBeaconProxy(this.beacon, data).then(instance => this.v1.attach(instance));
+
+ // test initial values
+ expect(await proxy.value()).to.equal(value);
+
+ // test initial version
+ expect(await proxy.version()).to.equal('V1');
+
+ // upgrade beacon
+ await this.beacon.connect(this.admin).upgradeTo(this.v2);
+
+ // test upgraded version
+ expect(await proxy.version()).to.equal('V2');
+ });
+
+ it('upgrade 2 proxies by upgrading shared beacon', async function () {
+ const value1 = 10n;
+ const data1 = this.v1.interface.encodeFunctionData('initializeNonPayableWithValue', [value1]);
+ const proxy1 = await this.newBeaconProxy(this.beacon, data1).then(instance => this.v1.attach(instance));
+
+ const value2 = 42n;
+ const data2 = this.v1.interface.encodeFunctionData('initializeNonPayableWithValue', [value2]);
+ const proxy2 = await this.newBeaconProxy(this.beacon, data2).then(instance => this.v1.attach(instance));
+
+ // test initial values
+ expect(await proxy1.value()).to.equal(value1);
+ expect(await proxy2.value()).to.equal(value2);
+
+ // test initial version
+ expect(await proxy1.version()).to.equal('V1');
+ expect(await proxy2.version()).to.equal('V1');
+
+ // upgrade beacon
+ await this.beacon.connect(this.admin).upgradeTo(this.v2);
+
+ // test upgraded version
+ expect(await proxy1.version()).to.equal('V2');
+ expect(await proxy2.version()).to.equal('V2');
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/beacon/UpgradeableBeacon.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/beacon/UpgradeableBeacon.test.js
new file mode 100644
index 000000000..2da7d0a27
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/beacon/UpgradeableBeacon.test.js
@@ -0,0 +1,55 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [admin, other] = await ethers.getSigners();
+
+ const v1 = await ethers.deployContract('Implementation1');
+ const v2 = await ethers.deployContract('Implementation2');
+ const beacon = await ethers.deployContract('UpgradeableBeacon', [v1, admin]);
+
+ return { admin, other, beacon, v1, v2 };
+}
+
+describe('UpgradeableBeacon', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('cannot be created with non-contract implementation', async function () {
+ await expect(ethers.deployContract('UpgradeableBeacon', [this.other, this.admin]))
+ .to.be.revertedWithCustomError(this.beacon, 'BeaconInvalidImplementation')
+ .withArgs(this.other);
+ });
+
+ describe('once deployed', function () {
+ it('emits Upgraded event to the first implementation', async function () {
+ await expect(this.beacon.deploymentTransaction()).to.emit(this.beacon, 'Upgraded').withArgs(this.v1);
+ });
+
+ it('returns implementation', async function () {
+ expect(await this.beacon.implementation()).to.equal(this.v1);
+ });
+
+ it('can be upgraded by the admin', async function () {
+ await expect(this.beacon.connect(this.admin).upgradeTo(this.v2))
+ .to.emit(this.beacon, 'Upgraded')
+ .withArgs(this.v2);
+
+ expect(await this.beacon.implementation()).to.equal(this.v2);
+ });
+
+ it('cannot be upgraded to a non-contract', async function () {
+ await expect(this.beacon.connect(this.admin).upgradeTo(this.other))
+ .to.be.revertedWithCustomError(this.beacon, 'BeaconInvalidImplementation')
+ .withArgs(this.other);
+ });
+
+ it('cannot be upgraded by other account', async function () {
+ await expect(this.beacon.connect(this.other).upgradeTo(this.v2))
+ .to.be.revertedWithCustomError(this.beacon, 'OwnableUnauthorizedAccount')
+ .withArgs(this.other);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/ProxyAdmin.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/ProxyAdmin.test.js
new file mode 100644
index 000000000..df430d46a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/ProxyAdmin.test.js
@@ -0,0 +1,82 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getAddressInSlot, ImplementationSlot } = require('../../helpers/storage');
+
+async function fixture() {
+ const [admin, other] = await ethers.getSigners();
+
+ const v1 = await ethers.deployContract('DummyImplementation');
+ const v2 = await ethers.deployContract('DummyImplementationV2');
+
+ const proxy = await ethers
+ .deployContract('TransparentUpgradeableProxy', [v1, admin, '0x'])
+ .then(instance => ethers.getContractAt('ITransparentUpgradeableProxy', instance));
+
+ const proxyAdmin = await ethers.getContractAt(
+ 'ProxyAdmin',
+ ethers.getCreateAddress({ from: proxy.target, nonce: 1n }),
+ );
+
+ return { admin, other, v1, v2, proxy, proxyAdmin };
+}
+
+describe('ProxyAdmin', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('has an owner', async function () {
+ expect(await this.proxyAdmin.owner()).to.equal(this.admin);
+ });
+
+ it('has an interface version', async function () {
+ expect(await this.proxyAdmin.UPGRADE_INTERFACE_VERSION()).to.equal('5.0.0');
+ });
+
+ describe('without data', function () {
+ describe('with unauthorized account', function () {
+ it('fails to upgrade', async function () {
+ await expect(this.proxyAdmin.connect(this.other).upgradeAndCall(this.proxy, this.v2, '0x'))
+ .to.be.revertedWithCustomError(this.proxyAdmin, 'OwnableUnauthorizedAccount')
+ .withArgs(this.other);
+ });
+ });
+
+ describe('with authorized account', function () {
+ it('upgrades implementation', async function () {
+ await this.proxyAdmin.connect(this.admin).upgradeAndCall(this.proxy, this.v2, '0x');
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.v2);
+ });
+ });
+ });
+
+ describe('with data', function () {
+ describe('with unauthorized account', function () {
+ it('fails to upgrade', async function () {
+ const data = this.v1.interface.encodeFunctionData('initializeNonPayableWithValue', [1337n]);
+ await expect(this.proxyAdmin.connect(this.other).upgradeAndCall(this.proxy, this.v2, data))
+ .to.be.revertedWithCustomError(this.proxyAdmin, 'OwnableUnauthorizedAccount')
+ .withArgs(this.other);
+ });
+ });
+
+ describe('with authorized account', function () {
+ describe('with invalid callData', function () {
+ it('fails to upgrade', async function () {
+ const data = '0x12345678';
+ await expect(this.proxyAdmin.connect(this.admin).upgradeAndCall(this.proxy, this.v2, data)).to.be.reverted;
+ });
+ });
+
+ describe('with valid callData', function () {
+ it('upgrades implementation', async function () {
+ const data = this.v2.interface.encodeFunctionData('initializeNonPayableWithValue', [1337n]);
+ await this.proxyAdmin.connect(this.admin).upgradeAndCall(this.proxy, this.v2, data);
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.v2);
+ });
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js
new file mode 100644
index 000000000..8e1d62eaa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.behaviour.js
@@ -0,0 +1,357 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+const { impersonate } = require('../../helpers/account');
+const { getAddressInSlot, ImplementationSlot, AdminSlot } = require('../../helpers/storage');
+
+// createProxy, initialOwner, accounts
+module.exports = function shouldBehaveLikeTransparentUpgradeableProxy() {
+ before(async function () {
+ const implementationV0 = await ethers.deployContract('DummyImplementation');
+ const implementationV1 = await ethers.deployContract('DummyImplementation');
+
+ const createProxyWithImpersonatedProxyAdmin = async (logic, initData, opts = undefined) => {
+ const [proxy, tx] = await this.createProxy(logic, initData, opts).then(instance =>
+ Promise.all([ethers.getContractAt('ITransparentUpgradeableProxy', instance), instance.deploymentTransaction()]),
+ );
+
+ const proxyAdmin = await ethers.getContractAt(
+ 'ProxyAdmin',
+ ethers.getCreateAddress({ from: proxy.target, nonce: 1n }),
+ );
+ const proxyAdminAsSigner = await proxyAdmin.getAddress().then(impersonate);
+
+ return {
+ instance: logic.attach(proxy.target), // attaching proxy directly works well for everything except for event resolution
+ proxy,
+ proxyAdmin,
+ proxyAdminAsSigner,
+ tx,
+ };
+ };
+
+ Object.assign(this, {
+ implementationV0,
+ implementationV1,
+ createProxyWithImpersonatedProxyAdmin,
+ });
+ });
+
+ beforeEach(async function () {
+ Object.assign(this, await this.createProxyWithImpersonatedProxyAdmin(this.implementationV0, '0x'));
+ });
+
+ describe('implementation', function () {
+ it('returns the current implementation address', async function () {
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.implementationV0);
+ });
+
+ it('delegates to the implementation', async function () {
+ expect(await this.instance.get()).to.be.true;
+ });
+ });
+
+ describe('proxy admin', function () {
+ it('emits AdminChanged event during construction', async function () {
+ await expect(this.tx).to.emit(this.proxy, 'AdminChanged').withArgs(ethers.ZeroAddress, this.proxyAdmin);
+ });
+
+ it('sets the proxy admin in storage with the correct initial owner', async function () {
+ expect(await getAddressInSlot(this.proxy, AdminSlot)).to.equal(this.proxyAdmin);
+
+ expect(await this.proxyAdmin.owner()).to.equal(this.owner);
+ });
+
+ it('can overwrite the admin by the implementation', async function () {
+ await this.instance.unsafeOverrideAdmin(this.other);
+
+ const ERC1967AdminSlotValue = await getAddressInSlot(this.proxy, AdminSlot);
+ expect(ERC1967AdminSlotValue).to.equal(this.other);
+ expect(ERC1967AdminSlotValue).to.not.equal(this.proxyAdmin);
+
+ // Still allows previous admin to execute admin operations
+ await expect(this.proxy.connect(this.proxyAdminAsSigner).upgradeToAndCall(this.implementationV1, '0x'))
+ .to.emit(this.proxy, 'Upgraded')
+ .withArgs(this.implementationV1);
+ });
+ });
+
+ describe('upgradeToAndCall', function () {
+ describe('without migrations', function () {
+ beforeEach(async function () {
+ this.behavior = await ethers.deployContract('InitializableMock');
+ });
+
+ describe('when the call does not fail', function () {
+ beforeEach(function () {
+ this.initializeData = this.behavior.interface.encodeFunctionData('initializeWithX', [42n]);
+ });
+
+ describe('when the sender is the admin', function () {
+ const value = 10n ** 5n;
+
+ beforeEach(async function () {
+ this.tx = await this.proxy
+ .connect(this.proxyAdminAsSigner)
+ .upgradeToAndCall(this.behavior, this.initializeData, {
+ value,
+ });
+ });
+
+ it('upgrades to the requested implementation', async function () {
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behavior);
+ });
+
+ it('emits an event', async function () {
+ await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behavior);
+ });
+
+ it('calls the initializer function', async function () {
+ expect(await this.behavior.attach(this.proxy).x()).to.equal(42n);
+ });
+
+ it('sends given value to the proxy', async function () {
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(value);
+ });
+
+ it('uses the storage of the proxy', async function () {
+ // storage layout should look as follows:
+ // - 0: Initializable storage ++ initializerRan ++ onlyInitializingRan
+ // - 1: x
+ expect(await ethers.provider.getStorage(this.proxy, 1n)).to.equal(42n);
+ });
+ });
+
+ describe('when the sender is not the admin', function () {
+ it('reverts', async function () {
+ await expect(this.proxy.connect(this.other).upgradeToAndCall(this.behavior, this.initializeData)).to.be
+ .reverted;
+ });
+ });
+ });
+
+ describe('when the call does fail', function () {
+ beforeEach(function () {
+ this.initializeData = this.behavior.interface.encodeFunctionData('fail');
+ });
+
+ it('reverts', async function () {
+ await expect(this.proxy.connect(this.proxyAdminAsSigner).upgradeToAndCall(this.behavior, this.initializeData))
+ .to.be.reverted;
+ });
+ });
+ });
+
+ describe('with migrations', function () {
+ describe('when the sender is the admin', function () {
+ const value = 10n ** 5n;
+
+ describe('when upgrading to V1', function () {
+ beforeEach(async function () {
+ this.behaviorV1 = await ethers.deployContract('MigratableMockV1');
+ const v1MigrationData = this.behaviorV1.interface.encodeFunctionData('initialize', [42n]);
+
+ this.balancePreviousV1 = await ethers.provider.getBalance(this.proxy);
+ this.tx = await this.proxy
+ .connect(this.proxyAdminAsSigner)
+ .upgradeToAndCall(this.behaviorV1, v1MigrationData, {
+ value,
+ });
+ });
+
+ it('upgrades to the requested version and emits an event', async function () {
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV1);
+
+ await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV1);
+ });
+
+ it("calls the 'initialize' function and sends given value to the proxy", async function () {
+ expect(await this.behaviorV1.attach(this.proxy).x()).to.equal(42n);
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(this.balancePreviousV1 + value);
+ });
+
+ describe('when upgrading to V2', function () {
+ beforeEach(async function () {
+ this.behaviorV2 = await ethers.deployContract('MigratableMockV2');
+ const v2MigrationData = this.behaviorV2.interface.encodeFunctionData('migrate', [10n, 42n]);
+
+ this.balancePreviousV2 = await ethers.provider.getBalance(this.proxy);
+ this.tx = await this.proxy
+ .connect(this.proxyAdminAsSigner)
+ .upgradeToAndCall(this.behaviorV2, v2MigrationData, {
+ value,
+ });
+ });
+
+ it('upgrades to the requested version and emits an event', async function () {
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV2);
+
+ await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV2);
+ });
+
+ it("calls the 'migrate' function and sends given value to the proxy", async function () {
+ expect(await this.behaviorV2.attach(this.proxy).x()).to.equal(10n);
+ expect(await this.behaviorV2.attach(this.proxy).y()).to.equal(42n);
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(this.balancePreviousV2 + value);
+ });
+
+ describe('when upgrading to V3', function () {
+ beforeEach(async function () {
+ this.behaviorV3 = await ethers.deployContract('MigratableMockV3');
+ const v3MigrationData = this.behaviorV3.interface.encodeFunctionData('migrate()');
+
+ this.balancePreviousV3 = await ethers.provider.getBalance(this.proxy);
+ this.tx = await this.proxy
+ .connect(this.proxyAdminAsSigner)
+ .upgradeToAndCall(this.behaviorV3, v3MigrationData, {
+ value,
+ });
+ });
+
+ it('upgrades to the requested version and emits an event', async function () {
+ expect(await getAddressInSlot(this.proxy, ImplementationSlot)).to.equal(this.behaviorV3);
+
+ await expect(this.tx).to.emit(this.proxy, 'Upgraded').withArgs(this.behaviorV3);
+ });
+
+ it("calls the 'migrate' function and sends given value to the proxy", async function () {
+ expect(await this.behaviorV3.attach(this.proxy).x()).to.equal(42n);
+ expect(await this.behaviorV3.attach(this.proxy).y()).to.equal(10n);
+ expect(await ethers.provider.getBalance(this.proxy)).to.equal(this.balancePreviousV3 + value);
+ });
+ });
+ });
+ });
+ });
+
+ describe('when the sender is not the admin', function () {
+ it('reverts', async function () {
+ const behaviorV1 = await ethers.deployContract('MigratableMockV1');
+ const v1MigrationData = behaviorV1.interface.encodeFunctionData('initialize', [42n]);
+ await expect(this.proxy.connect(this.other).upgradeToAndCall(behaviorV1, v1MigrationData)).to.be.reverted;
+ });
+ });
+ });
+ });
+
+ describe('transparent proxy', function () {
+ beforeEach('creating proxy', async function () {
+ this.clashingImplV0 = await ethers.deployContract('ClashingImplementation');
+ this.clashingImplV1 = await ethers.deployContract('ClashingImplementation');
+
+ Object.assign(this, await this.createProxyWithImpersonatedProxyAdmin(this.clashingImplV0, '0x'));
+ });
+
+ it('proxy admin cannot call delegated functions', async function () {
+ const factory = await ethers.getContractFactory('TransparentUpgradeableProxy');
+
+ await expect(this.instance.connect(this.proxyAdminAsSigner).delegatedFunction()).to.be.revertedWithCustomError(
+ factory,
+ 'ProxyDeniedAdminAccess',
+ );
+ });
+
+ describe('when function names clash', function () {
+ it('executes the proxy function if the sender is the admin', async function () {
+ await expect(this.proxy.connect(this.proxyAdminAsSigner).upgradeToAndCall(this.clashingImplV1, '0x'))
+ .to.emit(this.proxy, 'Upgraded')
+ .withArgs(this.clashingImplV1);
+ });
+
+ it('delegates the call to implementation when sender is not the admin', async function () {
+ await expect(this.proxy.connect(this.other).upgradeToAndCall(this.clashingImplV1, '0x'))
+ .to.emit(this.instance, 'ClashingImplementationCall')
+ .to.not.emit(this.proxy, 'Upgraded');
+ });
+ });
+ });
+
+ describe('regression', function () {
+ const initializeData = '0x';
+
+ it('should add new function', async function () {
+ const impl1 = await ethers.deployContract('Implementation1');
+ const impl2 = await ethers.deployContract('Implementation2');
+ const { instance, proxy, proxyAdminAsSigner } = await this.createProxyWithImpersonatedProxyAdmin(
+ impl1,
+ initializeData,
+ );
+
+ await instance.setValue(42n);
+
+ // `getValue` is not available in impl1
+ await expect(impl2.attach(instance).getValue()).to.be.reverted;
+
+ // do upgrade
+ await proxy.connect(proxyAdminAsSigner).upgradeToAndCall(impl2, '0x');
+
+ // `getValue` is available in impl2
+ expect(await impl2.attach(instance).getValue()).to.equal(42n);
+ });
+
+ it('should remove function', async function () {
+ const impl1 = await ethers.deployContract('Implementation1');
+ const impl2 = await ethers.deployContract('Implementation2');
+ const { instance, proxy, proxyAdminAsSigner } = await this.createProxyWithImpersonatedProxyAdmin(
+ impl2,
+ initializeData,
+ );
+
+ await instance.setValue(42n);
+
+ // `getValue` is available in impl2
+ expect(await impl2.attach(instance).getValue()).to.equal(42n);
+
+ // do downgrade
+ await proxy.connect(proxyAdminAsSigner).upgradeToAndCall(impl1, '0x');
+
+ // `getValue` is not available in impl1
+ await expect(impl2.attach(instance).getValue()).to.be.reverted;
+ });
+
+ it('should change function signature', async function () {
+ const impl1 = await ethers.deployContract('Implementation1');
+ const impl3 = await ethers.deployContract('Implementation3');
+ const { instance, proxy, proxyAdminAsSigner } = await this.createProxyWithImpersonatedProxyAdmin(
+ impl1,
+ initializeData,
+ );
+
+ await instance.setValue(42n);
+
+ await proxy.connect(proxyAdminAsSigner).upgradeToAndCall(impl3, '0x');
+
+ expect(await impl3.attach(instance).getValue(8n)).to.equal(50n);
+ });
+
+ it('should add fallback function', async function () {
+ const impl1 = await ethers.deployContract('Implementation1');
+ const impl4 = await ethers.deployContract('Implementation4');
+ const { instance, proxy, proxyAdminAsSigner } = await this.createProxyWithImpersonatedProxyAdmin(
+ impl1,
+ initializeData,
+ );
+
+ await proxy.connect(proxyAdminAsSigner).upgradeToAndCall(impl4, '0x');
+
+ await this.other.sendTransaction({ to: proxy });
+
+ expect(await impl4.attach(instance).getValue()).to.equal(1n);
+ });
+
+ it('should remove fallback function', async function () {
+ const impl2 = await ethers.deployContract('Implementation2');
+ const impl4 = await ethers.deployContract('Implementation4');
+ const { instance, proxy, proxyAdminAsSigner } = await this.createProxyWithImpersonatedProxyAdmin(
+ impl4,
+ initializeData,
+ );
+
+ await proxy.connect(proxyAdminAsSigner).upgradeToAndCall(impl2, '0x');
+
+ await expect(this.other.sendTransaction({ to: proxy })).to.be.reverted;
+
+ expect(await impl2.attach(instance).getValue()).to.equal(0n);
+ });
+ });
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.test.js
new file mode 100644
index 000000000..61e18014e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/transparent/TransparentUpgradeableProxy.test.js
@@ -0,0 +1,28 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const shouldBehaveLikeProxy = require('../Proxy.behaviour');
+const shouldBehaveLikeTransparentUpgradeableProxy = require('./TransparentUpgradeableProxy.behaviour');
+
+async function fixture() {
+ const [owner, other, ...accounts] = await ethers.getSigners();
+
+ const implementation = await ethers.deployContract('DummyImplementation');
+
+ const createProxy = function (logic, initData, opts = undefined) {
+ return ethers.deployContract('TransparentUpgradeableProxy', [logic, owner, initData], opts);
+ };
+
+ return { nonContractAddress: owner, owner, other, accounts, implementation, createProxy };
+}
+
+describe('TransparentUpgradeableProxy', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeProxy();
+
+ // createProxy, owner, otherAccounts
+ shouldBehaveLikeTransparentUpgradeableProxy();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/utils/Initializable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/utils/Initializable.test.js
new file mode 100644
index 000000000..6bf213f0d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/utils/Initializable.test.js
@@ -0,0 +1,216 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { MAX_UINT64 } = require('../../helpers/constants');
+
+describe('Initializable', function () {
+ describe('basic testing without inheritance', function () {
+ beforeEach('deploying', async function () {
+ this.mock = await ethers.deployContract('InitializableMock');
+ });
+
+ describe('before initialize', function () {
+ it('initializer has not run', async function () {
+ expect(await this.mock.initializerRan()).to.be.false;
+ });
+
+ it('_initializing returns false before initialization', async function () {
+ expect(await this.mock.isInitializing()).to.be.false;
+ });
+ });
+
+ describe('after initialize', function () {
+ beforeEach('initializing', async function () {
+ await this.mock.initialize();
+ });
+
+ it('initializer has run', async function () {
+ expect(await this.mock.initializerRan()).to.be.true;
+ });
+
+ it('_initializing returns false after initialization', async function () {
+ expect(await this.mock.isInitializing()).to.be.false;
+ });
+
+ it('initializer does not run again', async function () {
+ await expect(this.mock.initialize()).to.be.revertedWithCustomError(this.mock, 'InvalidInitialization');
+ });
+ });
+
+ describe('nested under an initializer', function () {
+ it('initializer modifier reverts', async function () {
+ await expect(this.mock.initializerNested()).to.be.revertedWithCustomError(this.mock, 'InvalidInitialization');
+ });
+
+ it('onlyInitializing modifier succeeds', async function () {
+ await this.mock.onlyInitializingNested();
+ expect(await this.mock.onlyInitializingRan()).to.be.true;
+ });
+ });
+
+ it('cannot call onlyInitializable function outside the scope of an initializable function', async function () {
+ await expect(this.mock.initializeOnlyInitializing()).to.be.revertedWithCustomError(this.mock, 'NotInitializing');
+ });
+ });
+
+ it('nested initializer can run during construction', async function () {
+ const mock = await ethers.deployContract('ConstructorInitializableMock');
+ expect(await mock.initializerRan()).to.be.true;
+ expect(await mock.onlyInitializingRan()).to.be.true;
+ });
+
+ it('multiple constructor levels can be initializers', async function () {
+ const mock = await ethers.deployContract('ChildConstructorInitializableMock');
+ expect(await mock.initializerRan()).to.be.true;
+ expect(await mock.childInitializerRan()).to.be.true;
+ expect(await mock.onlyInitializingRan()).to.be.true;
+ });
+
+ describe('reinitialization', function () {
+ beforeEach('deploying', async function () {
+ this.mock = await ethers.deployContract('ReinitializerMock');
+ });
+
+ it('can reinitialize', async function () {
+ expect(await this.mock.counter()).to.equal(0n);
+ await this.mock.initialize();
+ expect(await this.mock.counter()).to.equal(1n);
+ await this.mock.reinitialize(2);
+ expect(await this.mock.counter()).to.equal(2n);
+ await this.mock.reinitialize(3);
+ expect(await this.mock.counter()).to.equal(3n);
+ });
+
+ it('can jump multiple steps', async function () {
+ expect(await this.mock.counter()).to.equal(0n);
+ await this.mock.initialize();
+ expect(await this.mock.counter()).to.equal(1n);
+ await this.mock.reinitialize(128);
+ expect(await this.mock.counter()).to.equal(2n);
+ });
+
+ it('cannot nest reinitializers', async function () {
+ expect(await this.mock.counter()).to.equal(0n);
+ await expect(this.mock.nestedReinitialize(2, 2)).to.be.revertedWithCustomError(
+ this.mock,
+ 'InvalidInitialization',
+ );
+ await expect(this.mock.nestedReinitialize(2, 3)).to.be.revertedWithCustomError(
+ this.mock,
+ 'InvalidInitialization',
+ );
+ await expect(this.mock.nestedReinitialize(3, 2)).to.be.revertedWithCustomError(
+ this.mock,
+ 'InvalidInitialization',
+ );
+ });
+
+ it('can chain reinitializers', async function () {
+ expect(await this.mock.counter()).to.equal(0n);
+ await this.mock.chainReinitialize(2, 3);
+ expect(await this.mock.counter()).to.equal(2n);
+ });
+
+ it('_getInitializedVersion returns right version', async function () {
+ await this.mock.initialize();
+ expect(await this.mock.getInitializedVersion()).to.equal(1n);
+ await this.mock.reinitialize(12);
+ expect(await this.mock.getInitializedVersion()).to.equal(12n);
+ });
+
+ describe('contract locking', function () {
+ it('prevents initialization', async function () {
+ await this.mock.disableInitializers();
+ await expect(this.mock.initialize()).to.be.revertedWithCustomError(this.mock, 'InvalidInitialization');
+ });
+
+ it('prevents re-initialization', async function () {
+ await this.mock.disableInitializers();
+ await expect(this.mock.reinitialize(255n)).to.be.revertedWithCustomError(this.mock, 'InvalidInitialization');
+ });
+
+ it('can lock contract after initialization', async function () {
+ await this.mock.initialize();
+ await this.mock.disableInitializers();
+ await expect(this.mock.reinitialize(255n)).to.be.revertedWithCustomError(this.mock, 'InvalidInitialization');
+ });
+ });
+ });
+
+ describe('events', function () {
+ it('constructor initialization emits event', async function () {
+ const mock = await ethers.deployContract('ConstructorInitializableMock');
+ await expect(mock.deploymentTransaction()).to.emit(mock, 'Initialized').withArgs(1n);
+ });
+
+ it('initialization emits event', async function () {
+ const mock = await ethers.deployContract('ReinitializerMock');
+ await expect(mock.initialize()).to.emit(mock, 'Initialized').withArgs(1n);
+ });
+
+ it('reinitialization emits event', async function () {
+ const mock = await ethers.deployContract('ReinitializerMock');
+ await expect(mock.reinitialize(128)).to.emit(mock, 'Initialized').withArgs(128n);
+ });
+
+ it('chained reinitialization emits multiple events', async function () {
+ const mock = await ethers.deployContract('ReinitializerMock');
+
+ await expect(mock.chainReinitialize(2, 3))
+ .to.emit(mock, 'Initialized')
+ .withArgs(2n)
+ .to.emit(mock, 'Initialized')
+ .withArgs(3n);
+ });
+ });
+
+ describe('complex testing with inheritance', function () {
+ const mother = 12n;
+ const gramps = '56';
+ const father = 34n;
+ const child = 78n;
+
+ beforeEach('deploying', async function () {
+ this.mock = await ethers.deployContract('SampleChild');
+ await this.mock.initialize(mother, gramps, father, child);
+ });
+
+ it('initializes human', async function () {
+ expect(await this.mock.isHuman()).to.be.true;
+ });
+
+ it('initializes mother', async function () {
+ expect(await this.mock.mother()).to.equal(mother);
+ });
+
+ it('initializes gramps', async function () {
+ expect(await this.mock.gramps()).to.equal(gramps);
+ });
+
+ it('initializes father', async function () {
+ expect(await this.mock.father()).to.equal(father);
+ });
+
+ it('initializes child', async function () {
+ expect(await this.mock.child()).to.equal(child);
+ });
+ });
+
+ describe('disabling initialization', function () {
+ it('old and new patterns in bad sequence', async function () {
+ const DisableBad1 = await ethers.getContractFactory('DisableBad1');
+ await expect(DisableBad1.deploy()).to.be.revertedWithCustomError(DisableBad1, 'InvalidInitialization');
+
+ const DisableBad2 = await ethers.getContractFactory('DisableBad2');
+ await expect(DisableBad2.deploy()).to.be.revertedWithCustomError(DisableBad2, 'InvalidInitialization');
+ });
+
+ it('old and new patterns in good sequence', async function () {
+ const ok = await ethers.deployContract('DisableOk');
+ await expect(ok.deploymentTransaction())
+ .to.emit(ok, 'Initialized')
+ .withArgs(1n)
+ .to.emit(ok, 'Initialized')
+ .withArgs(MAX_UINT64);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/utils/UUPSUpgradeable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/utils/UUPSUpgradeable.test.js
new file mode 100644
index 000000000..17f865761
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/proxy/utils/UUPSUpgradeable.test.js
@@ -0,0 +1,120 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getAddressInSlot, ImplementationSlot } = require('../../helpers/storage');
+
+async function fixture() {
+ const implInitial = await ethers.deployContract('UUPSUpgradeableMock');
+ const implUpgradeOk = await ethers.deployContract('UUPSUpgradeableMock');
+ const implUpgradeUnsafe = await ethers.deployContract('UUPSUpgradeableUnsafeMock');
+ const implUpgradeNonUUPS = await ethers.deployContract('NonUpgradeableMock');
+ const implUnsupportedUUID = await ethers.deployContract('UUPSUnsupportedProxiableUUID');
+ // Used for testing non ERC1967 compliant proxies (clones are proxies that don't use the ERC1967 implementation slot)
+ const cloneFactory = await ethers.deployContract('$Clones');
+
+ const instance = await ethers
+ .deployContract('ERC1967Proxy', [implInitial, '0x'])
+ .then(proxy => implInitial.attach(proxy.target));
+
+ return {
+ implInitial,
+ implUpgradeOk,
+ implUpgradeUnsafe,
+ implUpgradeNonUUPS,
+ implUnsupportedUUID,
+ cloneFactory,
+ instance,
+ };
+}
+
+describe('UUPSUpgradeable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('has an interface version', async function () {
+ expect(await this.instance.UPGRADE_INTERFACE_VERSION()).to.equal('5.0.0');
+ });
+
+ it('upgrade to upgradeable implementation', async function () {
+ await expect(this.instance.upgradeToAndCall(this.implUpgradeOk, '0x'))
+ .to.emit(this.instance, 'Upgraded')
+ .withArgs(this.implUpgradeOk);
+
+ expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeOk);
+ });
+
+ it('upgrade to upgradeable implementation with call', async function () {
+ expect(await this.instance.current()).to.equal(0n);
+
+ await expect(
+ this.instance.upgradeToAndCall(this.implUpgradeOk, this.implUpgradeOk.interface.encodeFunctionData('increment')),
+ )
+ .to.emit(this.instance, 'Upgraded')
+ .withArgs(this.implUpgradeOk);
+
+ expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeOk);
+
+ expect(await this.instance.current()).to.equal(1n);
+ });
+
+ it('calling upgradeTo on the implementation reverts', async function () {
+ await expect(this.implInitial.upgradeToAndCall(this.implUpgradeOk, '0x')).to.be.revertedWithCustomError(
+ this.implInitial,
+ 'UUPSUnauthorizedCallContext',
+ );
+ });
+
+ it('calling upgradeToAndCall on the implementation reverts', async function () {
+ await expect(
+ this.implInitial.upgradeToAndCall(
+ this.implUpgradeOk,
+ this.implUpgradeOk.interface.encodeFunctionData('increment'),
+ ),
+ ).to.be.revertedWithCustomError(this.implUpgradeOk, 'UUPSUnauthorizedCallContext');
+ });
+
+ it('calling upgradeToAndCall from a contract that is not an ERC1967 proxy (with the right implementation) reverts', async function () {
+ const instance = await this.cloneFactory.$clone
+ .staticCall(this.implUpgradeOk)
+ .then(address => this.implInitial.attach(address));
+ await this.cloneFactory.$clone(this.implUpgradeOk);
+
+ await expect(instance.upgradeToAndCall(this.implUpgradeUnsafe, '0x')).to.be.revertedWithCustomError(
+ instance,
+ 'UUPSUnauthorizedCallContext',
+ );
+ });
+
+ it('rejects upgrading to an unsupported UUID', async function () {
+ await expect(this.instance.upgradeToAndCall(this.implUnsupportedUUID, '0x'))
+ .to.be.revertedWithCustomError(this.instance, 'UUPSUnsupportedProxiableUUID')
+ .withArgs(ethers.id('invalid UUID'));
+ });
+
+ it('upgrade to and unsafe upgradeable implementation', async function () {
+ await expect(this.instance.upgradeToAndCall(this.implUpgradeUnsafe, '0x'))
+ .to.emit(this.instance, 'Upgraded')
+ .withArgs(this.implUpgradeUnsafe);
+
+ expect(await getAddressInSlot(this.instance, ImplementationSlot)).to.equal(this.implUpgradeUnsafe);
+ });
+
+ // delegate to a non existing upgradeTo function causes a low level revert
+ it('reject upgrade to non uups implementation', async function () {
+ await expect(this.instance.upgradeToAndCall(this.implUpgradeNonUUPS, '0x'))
+ .to.be.revertedWithCustomError(this.instance, 'ERC1967InvalidImplementation')
+ .withArgs(this.implUpgradeNonUUPS);
+ });
+
+ it('reject proxy address as implementation', async function () {
+ const otherInstance = await ethers
+ .deployContract('ERC1967Proxy', [this.implInitial, '0x'])
+ .then(proxy => this.implInitial.attach(proxy.target));
+
+ await expect(this.instance.upgradeToAndCall(otherInstance, '0x'))
+ .to.be.revertedWithCustomError(this.instance, 'ERC1967InvalidImplementation')
+ .withArgs(otherInstance);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/sanity.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/sanity.test.js
new file mode 100644
index 000000000..ea0175c48
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/sanity.test.js
@@ -0,0 +1,27 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ return {};
+}
+
+describe('Environment sanity', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('snapshot', function () {
+ let blockNumberBefore;
+
+ it('cache and mine', async function () {
+ blockNumberBefore = await ethers.provider.getBlockNumber();
+ await mine();
+ expect(await ethers.provider.getBlockNumber()).to.equal(blockNumberBefore + 1);
+ });
+
+ it('check snapshot', async function () {
+ expect(await ethers.provider.getBlockNumber()).to.equal(blockNumberBefore);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.behavior.js
new file mode 100644
index 000000000..d19b73251
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.behavior.js
@@ -0,0 +1,763 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
+
+const { RevertType } = require('../../helpers/enums');
+const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior');
+
+function shouldBehaveLikeERC1155() {
+ const firstTokenId = 1n;
+ const secondTokenId = 2n;
+ const unknownTokenId = 3n;
+
+ const firstTokenValue = 1000n;
+ const secondTokenValue = 2000n;
+
+ const RECEIVER_SINGLE_MAGIC_VALUE = '0xf23a6e61';
+ const RECEIVER_BATCH_MAGIC_VALUE = '0xbc197c81';
+
+ beforeEach(async function () {
+ [this.recipient, this.proxy, this.alice, this.bruce] = this.otherAccounts;
+ });
+
+ describe('like an ERC1155', function () {
+ describe('balanceOf', function () {
+ it('should return 0 when queried about the zero address', async function () {
+ expect(await this.token.balanceOf(ethers.ZeroAddress, firstTokenId)).to.equal(0n);
+ });
+
+ describe("when accounts don't own tokens", function () {
+ it('returns zero for given addresses', async function () {
+ expect(await this.token.balanceOf(this.alice, firstTokenId)).to.equal(0n);
+ expect(await this.token.balanceOf(this.bruce, secondTokenId)).to.equal(0n);
+ expect(await this.token.balanceOf(this.alice, unknownTokenId)).to.equal(0n);
+ });
+ });
+
+ describe('when accounts own some tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.alice, firstTokenId, firstTokenValue, '0x');
+ await this.token.$_mint(this.bruce, secondTokenId, secondTokenValue, '0x');
+ });
+
+ it('returns the amount of tokens owned by the given addresses', async function () {
+ expect(await this.token.balanceOf(this.alice, firstTokenId)).to.equal(firstTokenValue);
+ expect(await this.token.balanceOf(this.bruce, secondTokenId)).to.equal(secondTokenValue);
+ expect(await this.token.balanceOf(this.alice, unknownTokenId)).to.equal(0n);
+ });
+ });
+ });
+
+ describe('balanceOfBatch', function () {
+ it("reverts when input arrays don't match up", async function () {
+ const accounts1 = [this.alice, this.bruce, this.alice, this.bruce];
+ const ids1 = [firstTokenId, secondTokenId, unknownTokenId];
+
+ await expect(this.token.balanceOfBatch(accounts1, ids1))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(ids1.length, accounts1.length);
+
+ const accounts2 = [this.alice, this.bruce];
+ const ids2 = [firstTokenId, secondTokenId, unknownTokenId];
+ await expect(this.token.balanceOfBatch(accounts2, ids2))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(ids2.length, accounts2.length);
+ });
+
+ it('should return 0 as the balance when one of the addresses is the zero address', async function () {
+ const result = await this.token.balanceOfBatch(
+ [this.alice, this.bruce, ethers.ZeroAddress],
+ [firstTokenId, secondTokenId, unknownTokenId],
+ );
+ expect(result).to.deep.equal([0n, 0n, 0n]);
+ });
+
+ describe("when accounts don't own tokens", function () {
+ it('returns zeros for each account', async function () {
+ const result = await this.token.balanceOfBatch(
+ [this.alice, this.bruce, this.alice],
+ [firstTokenId, secondTokenId, unknownTokenId],
+ );
+ expect(result).to.deep.equal([0n, 0n, 0n]);
+ });
+ });
+
+ describe('when accounts own some tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.alice, firstTokenId, firstTokenValue, '0x');
+ await this.token.$_mint(this.bruce, secondTokenId, secondTokenValue, '0x');
+ });
+
+ it('returns amounts owned by each account in order passed', async function () {
+ const result = await this.token.balanceOfBatch(
+ [this.bruce, this.alice, this.alice],
+ [secondTokenId, firstTokenId, unknownTokenId],
+ );
+ expect(result).to.deep.equal([secondTokenValue, firstTokenValue, 0n]);
+ });
+
+ it('returns multiple times the balance of the same address when asked', async function () {
+ const result = await this.token.balanceOfBatch(
+ [this.alice, this.bruce, this.alice],
+ [firstTokenId, secondTokenId, firstTokenId],
+ );
+ expect(result).to.deep.equal([firstTokenValue, secondTokenValue, firstTokenValue]);
+ });
+ });
+ });
+
+ describe('setApprovalForAll', function () {
+ beforeEach(async function () {
+ this.tx = await this.token.connect(this.holder).setApprovalForAll(this.proxy, true);
+ });
+
+ it('sets approval status which can be queried via isApprovedForAll', async function () {
+ expect(await this.token.isApprovedForAll(this.holder, this.proxy)).to.be.true;
+ });
+
+ it('emits an ApprovalForAll log', async function () {
+ await expect(this.tx).to.emit(this.token, 'ApprovalForAll').withArgs(this.holder, this.proxy, true);
+ });
+
+ it('can unset approval for an operator', async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.proxy, false);
+ expect(await this.token.isApprovedForAll(this.holder, this.proxy)).to.be.false;
+ });
+
+ it('reverts if attempting to approve zero address as an operator', async function () {
+ await expect(this.token.connect(this.holder).setApprovalForAll(ethers.ZeroAddress, true))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidOperator')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('safeTransferFrom', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, firstTokenId, firstTokenValue, '0x');
+ await this.token.$_mint(this.holder, secondTokenId, secondTokenValue, '0x');
+ });
+
+ it('reverts when transferring more than balance', async function () {
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, this.recipient, firstTokenId, firstTokenValue + 1n, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InsufficientBalance')
+ .withArgs(this.holder, firstTokenValue, firstTokenValue + 1n, firstTokenId);
+ });
+
+ it('reverts when transferring to zero address', async function () {
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, ethers.ZeroAddress, firstTokenId, firstTokenValue, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ function transferWasSuccessful() {
+ it('debits transferred balance from sender', async function () {
+ expect(await this.token.balanceOf(this.args.from, this.args.id)).to.equal(0n);
+ });
+
+ it('credits transferred balance to receiver', async function () {
+ expect(await this.token.balanceOf(this.args.to, this.args.id)).to.equal(this.args.value);
+ });
+
+ it('emits a TransferSingle log', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'TransferSingle')
+ .withArgs(this.args.operator, this.args.from, this.args.to, this.args.id, this.args.value);
+ });
+ }
+
+ describe('when called by the holder', function () {
+ beforeEach(async function () {
+ this.args = {
+ operator: this.holder,
+ from: this.holder,
+ to: this.recipient,
+ id: firstTokenId,
+ value: firstTokenValue,
+ data: '0x',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeTransferFrom(this.args.from, this.args.to, this.args.id, this.args.value, this.args.data);
+ });
+
+ transferWasSuccessful();
+
+ it('preserves existing balances which are not transferred by holder', async function () {
+ expect(await this.token.balanceOf(this.holder, secondTokenId)).to.equal(secondTokenValue);
+ expect(await this.token.balanceOf(this.recipient, secondTokenId)).to.equal(0n);
+ });
+ });
+
+ describe('when called by an operator on behalf of the holder', function () {
+ describe('when operator is not approved by holder', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.proxy, false);
+ });
+
+ it('reverts', async function () {
+ await expect(
+ this.token
+ .connect(this.proxy)
+ .safeTransferFrom(this.holder, this.recipient, firstTokenId, firstTokenValue, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155MissingApprovalForAll')
+ .withArgs(this.proxy, this.holder);
+ });
+ });
+
+ describe('when operator is approved by holder', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.proxy, true);
+
+ this.args = {
+ operator: this.proxy,
+ from: this.holder,
+ to: this.recipient,
+ id: firstTokenId,
+ value: firstTokenValue,
+ data: '0x',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeTransferFrom(this.args.from, this.args.to, this.args.id, this.args.value, this.args.data);
+ });
+
+ transferWasSuccessful();
+
+ it("preserves operator's balances not involved in the transfer", async function () {
+ expect(await this.token.balanceOf(this.proxy, firstTokenId)).to.equal(0n);
+ expect(await this.token.balanceOf(this.proxy, secondTokenId)).to.equal(0n);
+ });
+ });
+ });
+
+ describe('when sending to a valid receiver', function () {
+ beforeEach(async function () {
+ this.receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.None,
+ ]);
+ });
+
+ describe('without data', function () {
+ beforeEach(async function () {
+ this.args = {
+ operator: this.holder,
+ from: this.holder,
+ to: this.receiver,
+ id: firstTokenId,
+ value: firstTokenValue,
+ data: '0x',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeTransferFrom(this.args.from, this.args.to, this.args.id, this.args.value, this.args.data);
+ });
+
+ transferWasSuccessful();
+
+ it('calls onERC1155Received', async function () {
+ await expect(this.tx)
+ .to.emit(this.receiver, 'Received')
+ .withArgs(this.args.operator, this.args.from, this.args.id, this.args.value, this.args.data, anyValue);
+ });
+ });
+
+ describe('with data', function () {
+ beforeEach(async function () {
+ this.args = {
+ operator: this.holder,
+ from: this.holder,
+ to: this.receiver,
+ id: firstTokenId,
+ value: firstTokenValue,
+ data: '0xf00dd00d',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeTransferFrom(this.args.from, this.args.to, this.args.id, this.args.value, this.args.data);
+ });
+
+ transferWasSuccessful();
+
+ it('calls onERC1155Received', async function () {
+ await expect(this.tx)
+ .to.emit(this.receiver, 'Received')
+ .withArgs(this.args.operator, this.args.from, this.args.id, this.args.value, this.args.data, anyValue);
+ });
+ });
+ });
+
+ describe('to a receiver contract returning unexpected value', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ '0x00c0ffee',
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.None,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, receiver, firstTokenId, firstTokenValue, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(receiver);
+ });
+ });
+
+ describe('to a receiver contract that reverts', function () {
+ describe('with a revert string', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.RevertWithMessage,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, receiver, firstTokenId, firstTokenValue, '0x'),
+ ).to.be.revertedWith('ERC1155ReceiverMock: reverting on receive');
+ });
+ });
+
+ describe('without a revert string', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.RevertWithoutMessage,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, receiver, firstTokenId, firstTokenValue, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(receiver);
+ });
+ });
+
+ describe('with a custom error', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.RevertWithCustomError,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, receiver, firstTokenId, firstTokenValue, '0x'),
+ )
+ .to.be.revertedWithCustomError(receiver, 'CustomError')
+ .withArgs(RECEIVER_SINGLE_MAGIC_VALUE);
+ });
+ });
+
+ describe('with a panic', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.Panic,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, receiver, firstTokenId, firstTokenValue, '0x'),
+ ).to.be.revertedWithPanic();
+ });
+ });
+ });
+
+ describe('to a contract that does not implement the required function', function () {
+ it('reverts', async function () {
+ const invalidReceiver = this.token;
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, invalidReceiver, firstTokenId, firstTokenValue, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(invalidReceiver);
+ });
+ });
+ });
+
+ describe('safeBatchTransferFrom', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, firstTokenId, firstTokenValue, '0x');
+ await this.token.$_mint(this.holder, secondTokenId, secondTokenValue, '0x');
+ });
+
+ it('reverts when transferring value more than any of balances', async function () {
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ this.recipient,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue + 1n],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InsufficientBalance')
+ .withArgs(this.holder, secondTokenValue, secondTokenValue + 1n, secondTokenId);
+ });
+
+ it("reverts when ids array length doesn't match values array length", async function () {
+ const ids1 = [firstTokenId];
+ const tokenValues1 = [firstTokenValue, secondTokenValue];
+
+ await expect(
+ this.token.connect(this.holder).safeBatchTransferFrom(this.holder, this.recipient, ids1, tokenValues1, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(ids1.length, tokenValues1.length);
+
+ const ids2 = [firstTokenId, secondTokenId];
+ const tokenValues2 = [firstTokenValue];
+
+ await expect(
+ this.token.connect(this.holder).safeBatchTransferFrom(this.holder, this.recipient, ids2, tokenValues2, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(ids2.length, tokenValues2.length);
+ });
+
+ it('reverts when transferring to zero address', async function () {
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ ethers.ZeroAddress,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('reverts when transferring from zero address', async function () {
+ await expect(
+ this.token.$_safeBatchTransferFrom(ethers.ZeroAddress, this.holder, [firstTokenId], [firstTokenValue], '0x'),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ function batchTransferWasSuccessful() {
+ it('debits transferred balances from sender', async function () {
+ const newBalances = await this.token.balanceOfBatch(
+ this.args.ids.map(() => this.args.from),
+ this.args.ids,
+ );
+ expect(newBalances).to.deep.equal(this.args.ids.map(() => 0n));
+ });
+
+ it('credits transferred balances to receiver', async function () {
+ const newBalances = await this.token.balanceOfBatch(
+ this.args.ids.map(() => this.args.to),
+ this.args.ids,
+ );
+ expect(newBalances).to.deep.equal(this.args.values);
+ });
+
+ it('emits a TransferBatch log', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'TransferBatch')
+ .withArgs(this.args.operator, this.args.from, this.args.to, this.args.ids, this.args.values);
+ });
+ }
+
+ describe('when called by the holder', function () {
+ beforeEach(async function () {
+ this.args = {
+ operator: this.holder,
+ from: this.holder,
+ to: this.recipient,
+ ids: [firstTokenId, secondTokenId],
+ values: [firstTokenValue, secondTokenValue],
+ data: '0x',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeBatchTransferFrom(this.args.from, this.args.to, this.args.ids, this.args.values, this.args.data);
+ });
+
+ batchTransferWasSuccessful();
+ });
+
+ describe('when called by an operator on behalf of the holder', function () {
+ describe('when operator is not approved by holder', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.proxy, false);
+ });
+
+ it('reverts', async function () {
+ await expect(
+ this.token
+ .connect(this.proxy)
+ .safeBatchTransferFrom(
+ this.holder,
+ this.recipient,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155MissingApprovalForAll')
+ .withArgs(this.proxy, this.holder);
+ });
+ });
+
+ describe('when operator is approved by holder', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.proxy, true);
+
+ this.args = {
+ operator: this.proxy,
+ from: this.holder,
+ to: this.recipient,
+ ids: [firstTokenId, secondTokenId],
+ values: [firstTokenValue, secondTokenValue],
+ data: '0x',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeBatchTransferFrom(this.args.from, this.args.to, this.args.ids, this.args.values, this.args.data);
+ });
+
+ batchTransferWasSuccessful();
+
+ it("preserves operator's balances not involved in the transfer", async function () {
+ expect(await this.token.balanceOf(this.proxy, firstTokenId)).to.equal(0n);
+ expect(await this.token.balanceOf(this.proxy, secondTokenId)).to.equal(0n);
+ });
+ });
+ });
+
+ describe('when sending to a valid receiver', function () {
+ beforeEach(async function () {
+ this.receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.None,
+ ]);
+ });
+
+ describe('without data', function () {
+ beforeEach(async function () {
+ this.args = {
+ operator: this.holder,
+ from: this.holder,
+ to: this.receiver,
+ ids: [firstTokenId, secondTokenId],
+ values: [firstTokenValue, secondTokenValue],
+ data: '0x',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeBatchTransferFrom(this.args.from, this.args.to, this.args.ids, this.args.values, this.args.data);
+ });
+
+ batchTransferWasSuccessful();
+
+ it('calls onERC1155BatchReceived', async function () {
+ await expect(this.tx)
+ .to.emit(this.receiver, 'BatchReceived')
+ .withArgs(this.holder, this.holder, this.args.ids, this.args.values, this.args.data, anyValue);
+ });
+ });
+
+ describe('with data', function () {
+ beforeEach(async function () {
+ this.args = {
+ operator: this.holder,
+ from: this.holder,
+ to: this.receiver,
+ ids: [firstTokenId, secondTokenId],
+ values: [firstTokenValue, secondTokenValue],
+ data: '0xf00dd00d',
+ };
+ this.tx = await this.token
+ .connect(this.args.operator)
+ .safeBatchTransferFrom(this.args.from, this.args.to, this.args.ids, this.args.values, this.args.data);
+ });
+
+ batchTransferWasSuccessful();
+
+ it('calls onERC1155Received', async function () {
+ await expect(this.tx)
+ .to.emit(this.receiver, 'BatchReceived')
+ .withArgs(this.holder, this.holder, this.args.ids, this.args.values, this.args.data, anyValue);
+ });
+ });
+ });
+
+ describe('to a receiver contract returning unexpected value', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RevertType.None,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ receiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(receiver);
+ });
+ });
+
+ describe('to a receiver contract that reverts', function () {
+ describe('with a revert string', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.RevertWithMessage,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ receiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ ).to.be.revertedWith('ERC1155ReceiverMock: reverting on batch receive');
+ });
+ });
+
+ describe('without a revert string', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.RevertWithoutMessage,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ receiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(receiver);
+ });
+ });
+
+ describe('with a custom error', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.RevertWithCustomError,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ receiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(receiver, 'CustomError')
+ .withArgs(RECEIVER_SINGLE_MAGIC_VALUE);
+ });
+ });
+
+ describe('with a panic', function () {
+ it('reverts', async function () {
+ const receiver = await ethers.deployContract('$ERC1155ReceiverMock', [
+ RECEIVER_SINGLE_MAGIC_VALUE,
+ RECEIVER_BATCH_MAGIC_VALUE,
+ RevertType.Panic,
+ ]);
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ receiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ ).to.be.revertedWithPanic();
+ });
+ });
+ });
+
+ describe('to a contract that does not implement the required function', function () {
+ it('reverts', async function () {
+ const invalidReceiver = this.token;
+
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(
+ this.holder,
+ invalidReceiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(invalidReceiver);
+ });
+ });
+ });
+
+ shouldSupportInterfaces(['ERC1155', 'ERC1155MetadataURI']);
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeERC1155,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.test.js
new file mode 100644
index 000000000..8b0a672b2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/ERC1155.test.js
@@ -0,0 +1,213 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { zip } = require('../../helpers/iterate');
+const { shouldBehaveLikeERC1155 } = require('./ERC1155.behavior');
+
+const initialURI = 'https://token-cdn-domain/{id}.json';
+
+async function fixture() {
+ const [operator, holder, ...otherAccounts] = await ethers.getSigners();
+ const token = await ethers.deployContract('$ERC1155', [initialURI]);
+ return { token, operator, holder, otherAccounts };
+}
+
+describe('ERC1155', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeERC1155();
+
+ describe('internal functions', function () {
+ const tokenId = 1990n;
+ const mintValue = 9001n;
+ const burnValue = 3000n;
+
+ const tokenBatchIds = [2000n, 2010n, 2020n];
+ const mintValues = [5000n, 10000n, 42195n];
+ const burnValues = [5000n, 9001n, 195n];
+
+ const data = '0x12345678';
+
+ describe('_mint', function () {
+ it('reverts with a zero destination address', async function () {
+ await expect(this.token.$_mint(ethers.ZeroAddress, tokenId, mintValue, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ describe('with minted tokens', function () {
+ beforeEach(async function () {
+ this.tx = await this.token.connect(this.operator).$_mint(this.holder, tokenId, mintValue, data);
+ });
+
+ it('emits a TransferSingle event', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'TransferSingle')
+ .withArgs(this.operator, ethers.ZeroAddress, this.holder, tokenId, mintValue);
+ });
+
+ it('credits the minted token value', async function () {
+ expect(await this.token.balanceOf(this.holder, tokenId)).to.equal(mintValue);
+ });
+ });
+ });
+
+ describe('_mintBatch', function () {
+ it('reverts with a zero destination address', async function () {
+ await expect(this.token.$_mintBatch(ethers.ZeroAddress, tokenBatchIds, mintValues, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('reverts if length of inputs do not match', async function () {
+ await expect(this.token.$_mintBatch(this.holder, tokenBatchIds, mintValues.slice(1), data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(tokenBatchIds.length, mintValues.length - 1);
+
+ await expect(this.token.$_mintBatch(this.holder, tokenBatchIds.slice(1), mintValues, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(tokenBatchIds.length - 1, mintValues.length);
+ });
+
+ describe('with minted batch of tokens', function () {
+ beforeEach(async function () {
+ this.tx = await this.token.connect(this.operator).$_mintBatch(this.holder, tokenBatchIds, mintValues, data);
+ });
+
+ it('emits a TransferBatch event', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'TransferBatch')
+ .withArgs(this.operator, ethers.ZeroAddress, this.holder, tokenBatchIds, mintValues);
+ });
+
+ it('credits the minted batch of tokens', async function () {
+ const holderBatchBalances = await this.token.balanceOfBatch(
+ tokenBatchIds.map(() => this.holder),
+ tokenBatchIds,
+ );
+
+ expect(holderBatchBalances).to.deep.equal(mintValues);
+ });
+ });
+ });
+
+ describe('_burn', function () {
+ it("reverts when burning the zero account's tokens", async function () {
+ await expect(this.token.$_burn(ethers.ZeroAddress, tokenId, mintValue))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('reverts when burning a non-existent token id', async function () {
+ await expect(this.token.$_burn(this.holder, tokenId, mintValue))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InsufficientBalance')
+ .withArgs(this.holder, 0, mintValue, tokenId);
+ });
+
+ it('reverts when burning more than available tokens', async function () {
+ await this.token.connect(this.operator).$_mint(this.holder, tokenId, mintValue, data);
+
+ await expect(this.token.$_burn(this.holder, tokenId, mintValue + 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InsufficientBalance')
+ .withArgs(this.holder, mintValue, mintValue + 1n, tokenId);
+ });
+
+ describe('with minted-then-burnt tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, tokenId, mintValue, data);
+ this.tx = await this.token.connect(this.operator).$_burn(this.holder, tokenId, burnValue);
+ });
+
+ it('emits a TransferSingle event', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'TransferSingle')
+ .withArgs(this.operator, this.holder, ethers.ZeroAddress, tokenId, burnValue);
+ });
+
+ it('accounts for both minting and burning', async function () {
+ expect(await this.token.balanceOf(this.holder, tokenId)).to.equal(mintValue - burnValue);
+ });
+ });
+ });
+
+ describe('_burnBatch', function () {
+ it("reverts when burning the zero account's tokens", async function () {
+ await expect(this.token.$_burnBatch(ethers.ZeroAddress, tokenBatchIds, burnValues))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('reverts if length of inputs do not match', async function () {
+ await expect(this.token.$_burnBatch(this.holder, tokenBatchIds, burnValues.slice(1)))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(tokenBatchIds.length, burnValues.length - 1);
+
+ await expect(this.token.$_burnBatch(this.holder, tokenBatchIds.slice(1), burnValues))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InvalidArrayLength')
+ .withArgs(tokenBatchIds.length - 1, burnValues.length);
+ });
+
+ it('reverts when burning a non-existent token id', async function () {
+ await expect(this.token.$_burnBatch(this.holder, tokenBatchIds, burnValues))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155InsufficientBalance')
+ .withArgs(this.holder, 0, burnValues[0], tokenBatchIds[0]);
+ });
+
+ describe('with minted-then-burnt tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mintBatch(this.holder, tokenBatchIds, mintValues, data);
+ this.tx = await this.token.connect(this.operator).$_burnBatch(this.holder, tokenBatchIds, burnValues);
+ });
+
+ it('emits a TransferBatch event', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'TransferBatch')
+ .withArgs(this.operator, this.holder, ethers.ZeroAddress, tokenBatchIds, burnValues);
+ });
+
+ it('accounts for both minting and burning', async function () {
+ const holderBatchBalances = await this.token.balanceOfBatch(
+ tokenBatchIds.map(() => this.holder),
+ tokenBatchIds,
+ );
+
+ expect(holderBatchBalances).to.deep.equal(
+ zip(mintValues, burnValues).map(([mintValue, burnValue]) => mintValue - burnValue),
+ );
+ });
+ });
+ });
+ });
+
+ describe('ERC1155MetadataURI', function () {
+ const firstTokenID = 42n;
+ const secondTokenID = 1337n;
+
+ it('emits no URI event in constructor', async function () {
+ await expect(this.token.deploymentTransaction()).to.not.emit(this.token, 'URI');
+ });
+
+ it('sets the initial URI for all token types', async function () {
+ expect(await this.token.uri(firstTokenID)).to.equal(initialURI);
+ expect(await this.token.uri(secondTokenID)).to.equal(initialURI);
+ });
+
+ describe('_setURI', function () {
+ const newURI = 'https://token-cdn-domain/{locale}/{id}.json';
+
+ it('emits no URI event', async function () {
+ await expect(this.token.$_setURI(newURI)).to.not.emit(this.token, 'URI');
+ });
+
+ it('sets the new URI for all token types', async function () {
+ await this.token.$_setURI(newURI);
+
+ expect(await this.token.uri(firstTokenID)).to.equal(newURI);
+ expect(await this.token.uri(secondTokenID)).to.equal(newURI);
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Burnable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Burnable.test.js
new file mode 100644
index 000000000..01e7ee2ed
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Burnable.test.js
@@ -0,0 +1,66 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const ids = [42n, 1137n];
+const values = [3000n, 9902n];
+
+async function fixture() {
+ const [holder, operator, other] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC1155Burnable', ['https://token-cdn-domain/{id}.json']);
+ await token.$_mint(holder, ids[0], values[0], '0x');
+ await token.$_mint(holder, ids[1], values[1], '0x');
+
+ return { token, holder, operator, other };
+}
+
+describe('ERC1155Burnable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('burn', function () {
+ it('holder can burn their tokens', async function () {
+ await this.token.connect(this.holder).burn(this.holder, ids[0], values[0] - 1n);
+
+ expect(await this.token.balanceOf(this.holder, ids[0])).to.equal(1n);
+ });
+
+ it("approved operators can burn the holder's tokens", async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.operator, true);
+ await this.token.connect(this.operator).burn(this.holder, ids[0], values[0] - 1n);
+
+ expect(await this.token.balanceOf(this.holder, ids[0])).to.equal(1n);
+ });
+
+ it("unapproved accounts cannot burn the holder's tokens", async function () {
+ await expect(this.token.connect(this.other).burn(this.holder, ids[0], values[0] - 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155MissingApprovalForAll')
+ .withArgs(this.other, this.holder);
+ });
+ });
+
+ describe('burnBatch', function () {
+ it('holder can burn their tokens', async function () {
+ await this.token.connect(this.holder).burnBatch(this.holder, ids, [values[0] - 1n, values[1] - 2n]);
+
+ expect(await this.token.balanceOf(this.holder, ids[0])).to.equal(1n);
+ expect(await this.token.balanceOf(this.holder, ids[1])).to.equal(2n);
+ });
+
+ it("approved operators can burn the holder's tokens", async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.operator, true);
+ await this.token.connect(this.operator).burnBatch(this.holder, ids, [values[0] - 1n, values[1] - 2n]);
+
+ expect(await this.token.balanceOf(this.holder, ids[0])).to.equal(1n);
+ expect(await this.token.balanceOf(this.holder, ids[1])).to.equal(2n);
+ });
+
+ it("unapproved accounts cannot burn the holder's tokens", async function () {
+ await expect(this.token.connect(this.other).burnBatch(this.holder, ids, [values[0] - 1n, values[1] - 2n]))
+ .to.be.revertedWithCustomError(this.token, 'ERC1155MissingApprovalForAll')
+ .withArgs(this.other, this.holder);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Pausable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Pausable.test.js
new file mode 100644
index 000000000..81c4f69bc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Pausable.test.js
@@ -0,0 +1,105 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [holder, operator, receiver, other] = await ethers.getSigners();
+ const token = await ethers.deployContract('$ERC1155Pausable', ['https://token-cdn-domain/{id}.json']);
+ return { token, holder, operator, receiver, other };
+}
+
+describe('ERC1155Pausable', function () {
+ const firstTokenId = 37n;
+ const firstTokenValue = 42n;
+ const secondTokenId = 19842n;
+ const secondTokenValue = 23n;
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('when token is paused', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.operator, true);
+ await this.token.$_mint(this.holder, firstTokenId, firstTokenValue, '0x');
+ await this.token.$_pause();
+ });
+
+ it('reverts when trying to safeTransferFrom from holder', async function () {
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeTransferFrom(this.holder, this.receiver, firstTokenId, firstTokenValue, '0x'),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to safeTransferFrom from operator', async function () {
+ await expect(
+ this.token
+ .connect(this.operator)
+ .safeTransferFrom(this.holder, this.receiver, firstTokenId, firstTokenValue, '0x'),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to safeBatchTransferFrom from holder', async function () {
+ await expect(
+ this.token
+ .connect(this.holder)
+ .safeBatchTransferFrom(this.holder, this.receiver, [firstTokenId], [firstTokenValue], '0x'),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to safeBatchTransferFrom from operator', async function () {
+ await expect(
+ this.token
+ .connect(this.operator)
+ .safeBatchTransferFrom(this.holder, this.receiver, [firstTokenId], [firstTokenValue], '0x'),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to mint', async function () {
+ await expect(this.token.$_mint(this.holder, secondTokenId, secondTokenValue, '0x')).to.be.revertedWithCustomError(
+ this.token,
+ 'EnforcedPause',
+ );
+ });
+
+ it('reverts when trying to mintBatch', async function () {
+ await expect(
+ this.token.$_mintBatch(this.holder, [secondTokenId], [secondTokenValue], '0x'),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to burn', async function () {
+ await expect(this.token.$_burn(this.holder, firstTokenId, firstTokenValue)).to.be.revertedWithCustomError(
+ this.token,
+ 'EnforcedPause',
+ );
+ });
+
+ it('reverts when trying to burnBatch', async function () {
+ await expect(
+ this.token.$_burnBatch(this.holder, [firstTokenId], [firstTokenValue]),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ describe('setApprovalForAll', function () {
+ it('approves an operator', async function () {
+ await this.token.connect(this.holder).setApprovalForAll(this.other, true);
+ expect(await this.token.isApprovedForAll(this.holder, this.other)).to.be.true;
+ });
+ });
+
+ describe('balanceOf', function () {
+ it('returns the token value owned by the given address', async function () {
+ expect(await this.token.balanceOf(this.holder, firstTokenId)).to.equal(firstTokenValue);
+ });
+ });
+
+ describe('isApprovedForAll', function () {
+ it('returns the approval of the operator', async function () {
+ expect(await this.token.isApprovedForAll(this.holder, this.operator)).to.be.true;
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Supply.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Supply.test.js
new file mode 100644
index 000000000..cca36a0df
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155Supply.test.js
@@ -0,0 +1,119 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [holder] = await ethers.getSigners();
+ const token = await ethers.deployContract('$ERC1155Supply', ['https://token-cdn-domain/{id}.json']);
+ return { token, holder };
+}
+
+describe('ERC1155Supply', function () {
+ const firstTokenId = 37n;
+ const firstTokenValue = 42n;
+ const secondTokenId = 19842n;
+ const secondTokenValue = 23n;
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('before mint', function () {
+ it('exist', async function () {
+ expect(await this.token.exists(firstTokenId)).to.be.false;
+ });
+
+ it('totalSupply', async function () {
+ expect(await this.token.totalSupply(ethers.Typed.uint256(firstTokenId))).to.equal(0n);
+ expect(await this.token.totalSupply()).to.equal(0n);
+ });
+ });
+
+ describe('after mint', function () {
+ describe('single', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, firstTokenId, firstTokenValue, '0x');
+ });
+
+ it('exist', async function () {
+ expect(await this.token.exists(firstTokenId)).to.be.true;
+ });
+
+ it('totalSupply', async function () {
+ expect(await this.token.totalSupply(ethers.Typed.uint256(firstTokenId))).to.equal(firstTokenValue);
+ expect(await this.token.totalSupply()).to.equal(firstTokenValue);
+ });
+ });
+
+ describe('batch', function () {
+ beforeEach(async function () {
+ await this.token.$_mintBatch(
+ this.holder,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ );
+ });
+
+ it('exist', async function () {
+ expect(await this.token.exists(firstTokenId)).to.be.true;
+ expect(await this.token.exists(secondTokenId)).to.be.true;
+ });
+
+ it('totalSupply', async function () {
+ expect(await this.token.totalSupply(ethers.Typed.uint256(firstTokenId))).to.equal(firstTokenValue);
+ expect(await this.token.totalSupply(ethers.Typed.uint256(secondTokenId))).to.equal(secondTokenValue);
+ expect(await this.token.totalSupply()).to.equal(firstTokenValue + secondTokenValue);
+ });
+ });
+ });
+
+ describe('after burn', function () {
+ describe('single', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, firstTokenId, firstTokenValue, '0x');
+ await this.token.$_burn(this.holder, firstTokenId, firstTokenValue);
+ });
+
+ it('exist', async function () {
+ expect(await this.token.exists(firstTokenId)).to.be.false;
+ });
+
+ it('totalSupply', async function () {
+ expect(await this.token.totalSupply(ethers.Typed.uint256(firstTokenId))).to.equal(0n);
+ expect(await this.token.totalSupply()).to.equal(0n);
+ });
+ });
+
+ describe('batch', function () {
+ beforeEach(async function () {
+ await this.token.$_mintBatch(
+ this.holder,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ );
+ await this.token.$_burnBatch(this.holder, [firstTokenId, secondTokenId], [firstTokenValue, secondTokenValue]);
+ });
+
+ it('exist', async function () {
+ expect(await this.token.exists(firstTokenId)).to.be.false;
+ expect(await this.token.exists(secondTokenId)).to.be.false;
+ });
+
+ it('totalSupply', async function () {
+ expect(await this.token.totalSupply(ethers.Typed.uint256(firstTokenId))).to.equal(0n);
+ expect(await this.token.totalSupply(ethers.Typed.uint256(secondTokenId))).to.equal(0n);
+ expect(await this.token.totalSupply()).to.equal(0n);
+ });
+ });
+ });
+
+ describe('other', function () {
+ it('supply unaffected by no-op', async function () {
+ await this.token.$_update(ethers.ZeroAddress, ethers.ZeroAddress, [firstTokenId], [firstTokenValue]);
+ expect(await this.token.totalSupply(ethers.Typed.uint256(firstTokenId))).to.equal(0n);
+ expect(await this.token.totalSupply()).to.equal(0n);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155URIStorage.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155URIStorage.test.js
new file mode 100644
index 000000000..a0d9b5704
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/extensions/ERC1155URIStorage.test.js
@@ -0,0 +1,70 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const erc1155Uri = 'https://token.com/nfts/';
+const baseUri = 'https://token.com/';
+const tokenId = 1n;
+const value = 3000n;
+
+describe('ERC1155URIStorage', function () {
+ describe('with base uri set', function () {
+ async function fixture() {
+ const [holder] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC1155URIStorage', [erc1155Uri]);
+ await token.$_setBaseURI(baseUri);
+ await token.$_mint(holder, tokenId, value, '0x');
+
+ return { token, holder };
+ }
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('can request the token uri, returning the erc1155 uri if no token uri was set', async function () {
+ expect(await this.token.uri(tokenId)).to.equal(erc1155Uri);
+ });
+
+ it('can request the token uri, returning the concatenated uri if a token uri was set', async function () {
+ const tokenUri = '1234/';
+ const expectedUri = `${baseUri}${tokenUri}`;
+
+ await expect(this.token.$_setURI(ethers.Typed.uint256(tokenId), tokenUri))
+ .to.emit(this.token, 'URI')
+ .withArgs(expectedUri, tokenId);
+
+ expect(await this.token.uri(tokenId)).to.equal(expectedUri);
+ });
+ });
+
+ describe('with base uri set to the empty string', function () {
+ async function fixture() {
+ const [holder] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC1155URIStorage', ['']);
+ await token.$_mint(holder, tokenId, value, '0x');
+
+ return { token, holder };
+ }
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('can request the token uri, returning an empty string if no token uri was set', async function () {
+ expect(await this.token.uri(tokenId)).to.equal('');
+ });
+
+ it('can request the token uri, returning the token uri if a token uri was set', async function () {
+ const tokenUri = 'ipfs://1234/';
+
+ await expect(this.token.$_setURI(ethers.Typed.uint256(tokenId), tokenUri))
+ .to.emit(this.token, 'URI')
+ .withArgs(tokenUri, tokenId);
+
+ expect(await this.token.uri(tokenId)).to.equal(tokenUri);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Holder.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Holder.test.js
new file mode 100644
index 000000000..9bff487ad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Holder.test.js
@@ -0,0 +1,56 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
+
+const ids = [1n, 2n, 3n];
+const values = [1000n, 2000n, 3000n];
+const data = '0x12345678';
+
+async function fixture() {
+ const [owner] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC1155', ['https://token-cdn-domain/{id}.json']);
+ const mock = await ethers.deployContract('$ERC1155Holder');
+
+ await token.$_mintBatch(owner, ids, values, '0x');
+
+ return { owner, token, mock };
+}
+
+describe('ERC1155Holder', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldSupportInterfaces(['ERC1155Receiver']);
+
+ it('receives ERC1155 tokens from a single ID', async function () {
+ await this.token.connect(this.owner).safeTransferFrom(this.owner, this.mock, ids[0], values[0], data);
+
+ expect(await this.token.balanceOf(this.mock, ids[0])).to.equal(values[0]);
+
+ for (let i = 1; i < ids.length; i++) {
+ expect(await this.token.balanceOf(this.mock, ids[i])).to.equal(0n);
+ }
+ });
+
+ it('receives ERC1155 tokens from a multiple IDs', async function () {
+ expect(
+ await this.token.balanceOfBatch(
+ ids.map(() => this.mock),
+ ids,
+ ),
+ ).to.deep.equal(ids.map(() => 0n));
+
+ await this.token.connect(this.owner).safeBatchTransferFrom(this.owner, this.mock, ids, values, data);
+
+ expect(
+ await this.token.balanceOfBatch(
+ ids.map(() => this.mock),
+ ids,
+ ),
+ ).to.deep.equal(values);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Utils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Utils.test.js
new file mode 100644
index 000000000..5687568d3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC1155/utils/ERC1155Utils.test.js
@@ -0,0 +1,299 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { RevertType } = require('../../../helpers/enums');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const firstTokenId = 1n;
+const secondTokenId = 2n;
+const firstTokenValue = 1000n;
+const secondTokenValue = 1000n;
+
+const RECEIVER_SINGLE_MAGIC_VALUE = '0xf23a6e61';
+const RECEIVER_BATCH_MAGIC_VALUE = '0xbc197c81';
+
+const deployReceiver = (
+ revertType,
+ returnValueSingle = RECEIVER_SINGLE_MAGIC_VALUE,
+ returnValueBatched = RECEIVER_BATCH_MAGIC_VALUE,
+) => ethers.deployContract('$ERC1155ReceiverMock', [returnValueSingle, returnValueBatched, revertType]);
+
+const fixture = async () => {
+ const [eoa, operator, owner] = await ethers.getSigners();
+ const utils = await ethers.deployContract('$ERC1155Utils');
+
+ const receivers = {
+ correct: await deployReceiver(RevertType.None),
+ invalid: await deployReceiver(RevertType.None, '0xdeadbeef', '0xdeadbeef'),
+ message: await deployReceiver(RevertType.RevertWithMessage),
+ empty: await deployReceiver(RevertType.RevertWithoutMessage),
+ customError: await deployReceiver(RevertType.RevertWithCustomError),
+ panic: await deployReceiver(RevertType.Panic),
+ nonReceiver: await ethers.deployContract('CallReceiverMock'),
+ eoa,
+ };
+
+ return { operator, owner, utils, receivers };
+};
+
+describe('ERC1155Utils', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('onERC1155Received', function () {
+ it('succeeds when called by an EOA', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.eoa,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ ).to.not.be.reverted;
+ });
+
+ it('succeeds when data is passed', async function () {
+ const data = '0x12345678';
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.correct,
+ firstTokenId,
+ firstTokenValue,
+ data,
+ ),
+ ).to.not.be.reverted;
+ });
+
+ it('succeeds when data is empty', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.correct,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ ).to.not.be.reverted;
+ });
+
+ it('reverts when receiver returns invalid value', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.invalid,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC1155InvalidReceiver')
+ .withArgs(this.receivers.invalid);
+ });
+
+ it('reverts when receiver reverts with message', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.message,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ ).to.be.revertedWith('ERC1155ReceiverMock: reverting on receive');
+ });
+
+ it('reverts when receiver reverts without message', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.empty,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC1155InvalidReceiver')
+ .withArgs(this.receivers.empty);
+ });
+
+ it('reverts when receiver reverts with custom error', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.customError,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.receivers.customError, 'CustomError')
+ .withArgs(RECEIVER_SINGLE_MAGIC_VALUE);
+ });
+
+ it('reverts when receiver panics', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.panic,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ ).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+
+ it('reverts when receiver does not implement onERC1155Received', async function () {
+ await expect(
+ this.utils.$checkOnERC1155Received(
+ this.operator,
+ this.owner,
+ this.receivers.nonReceiver,
+ firstTokenId,
+ firstTokenValue,
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC1155InvalidReceiver')
+ .withArgs(this.receivers.nonReceiver);
+ });
+ });
+
+ describe('onERC1155BatchReceived', function () {
+ it('succeeds when called by an EOA', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.eoa,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ ).to.not.be.reverted;
+ });
+
+ it('succeeds when data is passed', async function () {
+ const data = '0x12345678';
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.correct,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ data,
+ ),
+ ).to.not.be.reverted;
+ });
+
+ it('succeeds when data is empty', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.correct,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ ).to.not.be.reverted;
+ });
+
+ it('reverts when receiver returns invalid value', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.invalid,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC1155InvalidReceiver')
+ .withArgs(this.receivers.invalid);
+ });
+
+ it('reverts when receiver reverts with message', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.message,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ ).to.be.revertedWith('ERC1155ReceiverMock: reverting on batch receive');
+ });
+
+ it('reverts when receiver reverts without message', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.empty,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC1155InvalidReceiver')
+ .withArgs(this.receivers.empty);
+ });
+
+ it('reverts when receiver reverts with custom error', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.customError,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.receivers.customError, 'CustomError')
+ .withArgs(RECEIVER_SINGLE_MAGIC_VALUE);
+ });
+
+ it('reverts when receiver panics', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.panic,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ ).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+
+ it('reverts when receiver does not implement onERC1155BatchReceived', async function () {
+ await expect(
+ this.utils.$checkOnERC1155BatchReceived(
+ this.operator,
+ this.owner,
+ this.receivers.nonReceiver,
+ [firstTokenId, secondTokenId],
+ [firstTokenValue, secondTokenValue],
+ '0x',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC1155InvalidReceiver')
+ .withArgs(this.receivers.nonReceiver);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/ERC20.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/ERC20.behavior.js
new file mode 100644
index 000000000..748df4b85
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/ERC20.behavior.js
@@ -0,0 +1,269 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+function shouldBehaveLikeERC20(initialSupply, opts = {}) {
+ const { forcedApproval } = opts;
+
+ beforeEach(async function () {
+ [this.holder, this.recipient, this.other] = this.accounts;
+ });
+
+ it('total supply: returns the total token value', async function () {
+ expect(await this.token.totalSupply()).to.equal(initialSupply);
+ });
+
+ describe('balanceOf', function () {
+ it('returns zero when the requested account has no tokens', async function () {
+ expect(await this.token.balanceOf(this.other)).to.equal(0n);
+ });
+
+ it('returns the total token value when the requested account has some tokens', async function () {
+ expect(await this.token.balanceOf(this.holder)).to.equal(initialSupply);
+ });
+ });
+
+ describe('transfer', function () {
+ beforeEach(function () {
+ this.transfer = (from, to, value) => this.token.connect(from).transfer(to, value);
+ });
+
+ shouldBehaveLikeERC20Transfer(initialSupply);
+ });
+
+ describe('transfer from', function () {
+ describe('when the token owner is not the zero address', function () {
+ describe('when the recipient is not the zero address', function () {
+ describe('when the spender has enough allowance', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).approve(this.recipient, initialSupply);
+ });
+
+ describe('when the token owner has enough balance', function () {
+ const value = initialSupply;
+
+ beforeEach(async function () {
+ this.tx = await this.token.connect(this.recipient).transferFrom(this.holder, this.other, value);
+ });
+
+ it('transfers the requested value', async function () {
+ await expect(this.tx).to.changeTokenBalances(this.token, [this.holder, this.other], [-value, value]);
+ });
+
+ it('decreases the spender allowance', async function () {
+ expect(await this.token.allowance(this.holder, this.recipient)).to.equal(0n);
+ });
+
+ it('emits a transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.holder, this.other, value);
+ });
+
+ if (forcedApproval) {
+ it('emits an approval event', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'Approval')
+ .withArgs(
+ this.holder.address,
+ this.recipient.address,
+ await this.token.allowance(this.holder, this.recipient),
+ );
+ });
+ } else {
+ it('does not emit an approval event', async function () {
+ await expect(this.tx).to.not.emit(this.token, 'Approval');
+ });
+ }
+ });
+
+ it('reverts when the token owner does not have enough balance', async function () {
+ const value = initialSupply;
+ await this.token.connect(this.holder).transfer(this.other, 1n);
+ await expect(this.token.connect(this.recipient).transferFrom(this.holder, this.other, value))
+ .to.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, value - 1n, value);
+ });
+ });
+
+ describe('when the spender does not have enough allowance', function () {
+ const allowance = initialSupply - 1n;
+
+ beforeEach(async function () {
+ await this.token.connect(this.holder).approve(this.recipient, allowance);
+ });
+
+ it('reverts when the token owner has enough balance', async function () {
+ const value = initialSupply;
+ await expect(this.token.connect(this.recipient).transferFrom(this.holder, this.other, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientAllowance')
+ .withArgs(this.recipient, allowance, value);
+ });
+
+ it('reverts when the token owner does not have enough balance', async function () {
+ const value = allowance;
+ await this.token.connect(this.holder).transfer(this.other, 2);
+ await expect(this.token.connect(this.recipient).transferFrom(this.holder, this.other, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, value - 1n, value);
+ });
+ });
+
+ describe('when the spender has unlimited allowance', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).approve(this.recipient, ethers.MaxUint256);
+ this.tx = await this.token.connect(this.recipient).transferFrom(this.holder, this.other, 1n);
+ });
+
+ it('does not decrease the spender allowance', async function () {
+ expect(await this.token.allowance(this.holder, this.recipient)).to.equal(ethers.MaxUint256);
+ });
+
+ it('does not emit an approval event', async function () {
+ await expect(this.tx).to.not.emit(this.token, 'Approval');
+ });
+ });
+ });
+
+ it('reverts when the recipient is the zero address', async function () {
+ const value = initialSupply;
+ await this.token.connect(this.holder).approve(this.recipient, value);
+ await expect(this.token.connect(this.recipient).transferFrom(this.holder, ethers.ZeroAddress, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ it('reverts when the token owner is the zero address', async function () {
+ // transferFrom does a spendAllowance before moving the assets
+ // - default behavior (ERC20) is to always update the approval using `_approve`. This will fail because the
+ // approver (owner) is address(0). This happens even if the amount transferred is zero, and the approval update
+ // is not actually necessary.
+ // - in ERC20TemporaryAllowance, transfer of 0 value will not update allowance (temporary or persistent)
+ // therefore the spendAllowance does not revert. However, the transfer of asset will revert because the sender
+ // is address(0)
+ const errorName = this.token.temporaryApprove ? 'ERC20InvalidSender' : 'ERC20InvalidApprover';
+
+ const value = 0n;
+ await expect(this.token.connect(this.recipient).transferFrom(ethers.ZeroAddress, this.recipient, value))
+ .to.be.revertedWithCustomError(this.token, errorName)
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('approve', function () {
+ beforeEach(function () {
+ this.approve = (owner, spender, value) => this.token.connect(owner).approve(spender, value);
+ });
+
+ shouldBehaveLikeERC20Approve(initialSupply);
+ });
+}
+
+function shouldBehaveLikeERC20Transfer(balance) {
+ describe('when the recipient is not the zero address', function () {
+ it('reverts when the sender does not have enough balance', async function () {
+ const value = balance + 1n;
+ await expect(this.transfer(this.holder, this.recipient, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, balance, value);
+ });
+
+ describe('when the sender transfers all balance', function () {
+ const value = balance;
+
+ beforeEach(async function () {
+ this.tx = await this.transfer(this.holder, this.recipient, value);
+ });
+
+ it('transfers the requested value', async function () {
+ await expect(this.tx).to.changeTokenBalances(this.token, [this.holder, this.recipient], [-value, value]);
+ });
+
+ it('emits a transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.holder, this.recipient, value);
+ });
+ });
+
+ describe('when the sender transfers zero tokens', function () {
+ const value = 0n;
+
+ beforeEach(async function () {
+ this.tx = await this.transfer(this.holder, this.recipient, value);
+ });
+
+ it('transfers the requested value', async function () {
+ await expect(this.tx).to.changeTokenBalances(this.token, [this.holder, this.recipient], [0n, 0n]);
+ });
+
+ it('emits a transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.holder, this.recipient, value);
+ });
+ });
+ });
+
+ it('reverts when the recipient is the zero address', async function () {
+ await expect(this.transfer(this.holder, ethers.ZeroAddress, balance))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+}
+
+function shouldBehaveLikeERC20Approve(supply) {
+ describe('when the spender is not the zero address', function () {
+ describe('when the sender has enough balance', function () {
+ const value = supply;
+
+ it('emits an approval event', async function () {
+ await expect(this.approve(this.holder, this.recipient, value))
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.holder, this.recipient, value);
+ });
+
+ it('approves the requested value when there was no approved value before', async function () {
+ await this.approve(this.holder, this.recipient, value);
+
+ expect(await this.token.allowance(this.holder, this.recipient)).to.equal(value);
+ });
+
+ it('approves the requested value and replaces the previous one when the spender had an approved value', async function () {
+ await this.approve(this.holder, this.recipient, 1n);
+ await this.approve(this.holder, this.recipient, value);
+
+ expect(await this.token.allowance(this.holder, this.recipient)).to.equal(value);
+ });
+ });
+
+ describe('when the sender does not have enough balance', function () {
+ const value = supply + 1n;
+
+ it('emits an approval event', async function () {
+ await expect(this.approve(this.holder, this.recipient, value))
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.holder, this.recipient, value);
+ });
+
+ it('approves the requested value when there was no approved value before', async function () {
+ await this.approve(this.holder, this.recipient, value);
+
+ expect(await this.token.allowance(this.holder, this.recipient)).to.equal(value);
+ });
+
+ it('approves the requested value and replaces the previous one when the spender had an approved value', async function () {
+ await this.approve(this.holder, this.recipient, 1n);
+ await this.approve(this.holder, this.recipient, value);
+
+ expect(await this.token.allowance(this.holder, this.recipient)).to.equal(value);
+ });
+ });
+ });
+
+ it('reverts when the spender is the zero address', async function () {
+ await expect(this.approve(this.holder, ethers.ZeroAddress, supply))
+ .to.be.revertedWithCustomError(this.token, `ERC20InvalidSpender`)
+ .withArgs(ethers.ZeroAddress);
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeERC20,
+ shouldBehaveLikeERC20Transfer,
+ shouldBehaveLikeERC20Approve,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/ERC20.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/ERC20.test.js
new file mode 100644
index 000000000..2d9eefe1c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/ERC20.test.js
@@ -0,0 +1,199 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const {
+ shouldBehaveLikeERC20,
+ shouldBehaveLikeERC20Transfer,
+ shouldBehaveLikeERC20Approve,
+} = require('./ERC20.behavior');
+
+const TOKENS = [{ Token: '$ERC20' }, { Token: '$ERC20ApprovalMock', forcedApproval: true }];
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const initialSupply = 100n;
+
+describe('ERC20', function () {
+ for (const { Token, forcedApproval } of TOKENS) {
+ describe(Token, function () {
+ const fixture = async () => {
+ // this.accounts is used by shouldBehaveLikeERC20
+ const accounts = await ethers.getSigners();
+ const [holder, recipient] = accounts;
+
+ const token = await ethers.deployContract(Token, [name, symbol]);
+ await token.$_mint(holder, initialSupply);
+
+ return { accounts, holder, recipient, token };
+ };
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeERC20(initialSupply, { forcedApproval });
+
+ it('has a name', async function () {
+ expect(await this.token.name()).to.equal(name);
+ });
+
+ it('has a symbol', async function () {
+ expect(await this.token.symbol()).to.equal(symbol);
+ });
+
+ it('has 18 decimals', async function () {
+ expect(await this.token.decimals()).to.equal(18n);
+ });
+
+ describe('_mint', function () {
+ const value = 50n;
+ it('rejects a null account', async function () {
+ await expect(this.token.$_mint(ethers.ZeroAddress, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('rejects overflow', async function () {
+ await expect(this.token.$_mint(this.recipient, ethers.MaxUint256)).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW,
+ );
+ });
+
+ describe('for a non zero account', function () {
+ beforeEach('minting', async function () {
+ this.tx = await this.token.$_mint(this.recipient, value);
+ });
+
+ it('increments totalSupply', async function () {
+ await expect(await this.token.totalSupply()).to.equal(initialSupply + value);
+ });
+
+ it('increments recipient balance', async function () {
+ await expect(this.tx).to.changeTokenBalance(this.token, this.recipient, value);
+ });
+
+ it('emits Transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(ethers.ZeroAddress, this.recipient, value);
+ });
+ });
+ });
+
+ describe('_burn', function () {
+ it('rejects a null account', async function () {
+ await expect(this.token.$_burn(ethers.ZeroAddress, 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ describe('for a non zero account', function () {
+ it('rejects burning more than balance', async function () {
+ await expect(this.token.$_burn(this.holder, initialSupply + 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, initialSupply, initialSupply + 1n);
+ });
+
+ const describeBurn = function (description, value) {
+ describe(description, function () {
+ beforeEach('burning', async function () {
+ this.tx = await this.token.$_burn(this.holder, value);
+ });
+
+ it('decrements totalSupply', async function () {
+ expect(await this.token.totalSupply()).to.equal(initialSupply - value);
+ });
+
+ it('decrements holder balance', async function () {
+ await expect(this.tx).to.changeTokenBalance(this.token, this.holder, -value);
+ });
+
+ it('emits Transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.holder, ethers.ZeroAddress, value);
+ });
+ });
+ };
+
+ describeBurn('for entire balance', initialSupply);
+ describeBurn('for less value than balance', initialSupply - 1n);
+ });
+ });
+
+ describe('_update', function () {
+ const value = 1n;
+
+ beforeEach(async function () {
+ this.totalSupply = await this.token.totalSupply();
+ });
+
+ it('from is the zero address', async function () {
+ const tx = await this.token.$_update(ethers.ZeroAddress, this.holder, value);
+ await expect(tx).to.emit(this.token, 'Transfer').withArgs(ethers.ZeroAddress, this.holder, value);
+
+ expect(await this.token.totalSupply()).to.equal(this.totalSupply + value);
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, value);
+ });
+
+ it('to is the zero address', async function () {
+ const tx = await this.token.$_update(this.holder, ethers.ZeroAddress, value);
+ await expect(tx).to.emit(this.token, 'Transfer').withArgs(this.holder, ethers.ZeroAddress, value);
+
+ expect(await this.token.totalSupply()).to.equal(this.totalSupply - value);
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, -value);
+ });
+
+ describe('from and to are the same address', function () {
+ it('zero address', async function () {
+ const tx = await this.token.$_update(ethers.ZeroAddress, ethers.ZeroAddress, value);
+ await expect(tx).to.emit(this.token, 'Transfer').withArgs(ethers.ZeroAddress, ethers.ZeroAddress, value);
+
+ expect(await this.token.totalSupply()).to.equal(this.totalSupply);
+ await expect(tx).to.changeTokenBalance(this.token, ethers.ZeroAddress, 0n);
+ });
+
+ describe('non zero address', function () {
+ it('reverts without balance', async function () {
+ await expect(this.token.$_update(this.recipient, this.recipient, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.recipient, 0n, value);
+ });
+
+ it('executes with balance', async function () {
+ const tx = await this.token.$_update(this.holder, this.holder, value);
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, 0n);
+ await expect(tx).to.emit(this.token, 'Transfer').withArgs(this.holder, this.holder, value);
+ });
+ });
+ });
+ });
+
+ describe('_transfer', function () {
+ beforeEach(function () {
+ this.transfer = this.token.$_transfer;
+ });
+
+ shouldBehaveLikeERC20Transfer(initialSupply);
+
+ it('reverts when the sender is the zero address', async function () {
+ await expect(this.token.$_transfer(ethers.ZeroAddress, this.recipient, initialSupply))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('_approve', function () {
+ beforeEach(function () {
+ this.approve = this.token.$_approve;
+ });
+
+ shouldBehaveLikeERC20Approve(initialSupply);
+
+ it('reverts when the owner is the zero address', async function () {
+ await expect(this.token.$_approve(ethers.ZeroAddress, this.recipient, initialSupply))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidApprover')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC1363.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC1363.test.js
new file mode 100644
index 000000000..3d1f4e58f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC1363.test.js
@@ -0,0 +1,370 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const {
+ shouldBehaveLikeERC20,
+ shouldBehaveLikeERC20Transfer,
+ shouldBehaveLikeERC20Approve,
+} = require('../ERC20.behavior.js');
+const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
+const { RevertType } = require('../../../helpers/enums.js');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const value = 1000n;
+const data = '0x123456';
+
+async function fixture() {
+ // this.accounts is used by shouldBehaveLikeERC20
+ const accounts = await ethers.getSigners();
+ const [holder, other] = accounts;
+
+ const receiver = await ethers.deployContract('ERC1363ReceiverMock');
+ const spender = await ethers.deployContract('ERC1363SpenderMock');
+ const token = await ethers.deployContract('$ERC1363', [name, symbol]);
+
+ await token.$_mint(holder, value);
+
+ return {
+ accounts,
+ holder,
+ other,
+ token,
+ receiver,
+ spender,
+ selectors: {
+ onTransferReceived: receiver.interface.getFunction('onTransferReceived(address,address,uint256,bytes)').selector,
+ onApprovalReceived: spender.interface.getFunction('onApprovalReceived(address,uint256,bytes)').selector,
+ },
+ };
+}
+
+describe('ERC1363', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldSupportInterfaces(['ERC165', 'ERC1363']);
+ shouldBehaveLikeERC20(value);
+
+ describe('transferAndCall', function () {
+ describe('as a transfer', function () {
+ beforeEach(async function () {
+ this.recipient = this.receiver;
+ this.transfer = (holder, ...rest) =>
+ this.token.connect(holder).getFunction('transferAndCall(address,uint256)')(...rest);
+ });
+
+ shouldBehaveLikeERC20Transfer(value);
+ });
+
+ it('reverts transferring to an EOA', async function () {
+ await expect(this.token.connect(this.holder).getFunction('transferAndCall(address,uint256)')(this.other, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.other.address);
+ });
+
+ it('succeeds without data', async function () {
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256)')(this.receiver, value),
+ )
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder.address, this.receiver.target, value)
+ .to.emit(this.receiver, 'Received')
+ .withArgs(this.holder.address, this.holder.address, value, '0x');
+ });
+
+ it('succeeds with data', async function () {
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256,bytes)')(
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder.address, this.receiver.target, value)
+ .to.emit(this.receiver, 'Received')
+ .withArgs(this.holder.address, this.holder.address, value, data);
+ });
+
+ it('reverts with reverting hook (without reason)', async function () {
+ await this.receiver.setUp(this.selectors.onTransferReceived, RevertType.RevertWithoutMessage);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256,bytes)')(
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.receiver.target);
+ });
+
+ it('reverts with reverting hook (with reason)', async function () {
+ await this.receiver.setUp(this.selectors.onTransferReceived, RevertType.RevertWithMessage);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256,bytes)')(
+ this.receiver,
+ value,
+ data,
+ ),
+ ).to.be.revertedWith('ERC1363ReceiverMock: reverting');
+ });
+
+ it('reverts with reverting hook (with custom error)', async function () {
+ const reason = '0x12345678';
+ await this.receiver.setUp(reason, RevertType.RevertWithCustomError);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256,bytes)')(
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.receiver, 'CustomError')
+ .withArgs(reason);
+ });
+
+ it('panics with reverting hook (with panic)', async function () {
+ await this.receiver.setUp(this.selectors.onTransferReceived, RevertType.Panic);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256,bytes)')(
+ this.receiver,
+ value,
+ data,
+ ),
+ ).to.be.revertedWithPanic();
+ });
+
+ it('reverts with bad return value', async function () {
+ await this.receiver.setUp('0x12345678', RevertType.None);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('transferAndCall(address,uint256,bytes)')(
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.receiver.target);
+ });
+ });
+
+ describe('transferFromAndCall', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).approve(this.other, ethers.MaxUint256);
+ });
+
+ describe('as a transfer', function () {
+ beforeEach(async function () {
+ this.recipient = this.receiver;
+ this.transfer = this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256)');
+ });
+
+ shouldBehaveLikeERC20Transfer(value);
+ });
+
+ it('reverts transferring to an EOA', async function () {
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256)')(
+ this.holder,
+ this.other,
+ value,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.other.address);
+ });
+
+ it('succeeds without data', async function () {
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256)')(
+ this.holder,
+ this.receiver,
+ value,
+ ),
+ )
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder.address, this.receiver.target, value)
+ .to.emit(this.receiver, 'Received')
+ .withArgs(this.other.address, this.holder.address, value, '0x');
+ });
+
+ it('succeeds with data', async function () {
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256,bytes)')(
+ this.holder,
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder.address, this.receiver.target, value)
+ .to.emit(this.receiver, 'Received')
+ .withArgs(this.other.address, this.holder.address, value, data);
+ });
+
+ it('reverts with reverting hook (without reason)', async function () {
+ await this.receiver.setUp(this.selectors.onTransferReceived, RevertType.RevertWithoutMessage);
+
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256,bytes)')(
+ this.holder,
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.receiver.target);
+ });
+
+ it('reverts with reverting hook (with reason)', async function () {
+ await this.receiver.setUp(this.selectors.onTransferReceived, RevertType.RevertWithMessage);
+
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256,bytes)')(
+ this.holder,
+ this.receiver,
+ value,
+ data,
+ ),
+ ).to.be.revertedWith('ERC1363ReceiverMock: reverting');
+ });
+
+ it('reverts with reverting hook (with custom error)', async function () {
+ const reason = '0x12345678';
+ await this.receiver.setUp(reason, RevertType.RevertWithCustomError);
+
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256,bytes)')(
+ this.holder,
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.receiver, 'CustomError')
+ .withArgs(reason);
+ });
+
+ it('panics with reverting hook (with panic)', async function () {
+ await this.receiver.setUp(this.selectors.onTransferReceived, RevertType.Panic);
+
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256,bytes)')(
+ this.holder,
+ this.receiver,
+ value,
+ data,
+ ),
+ ).to.be.revertedWithPanic();
+ });
+
+ it('reverts with bad return value', async function () {
+ await this.receiver.setUp('0x12345678', RevertType.None);
+
+ await expect(
+ this.token.connect(this.other).getFunction('transferFromAndCall(address,address,uint256,bytes)')(
+ this.holder,
+ this.receiver,
+ value,
+ data,
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.receiver.target);
+ });
+ });
+
+ describe('approveAndCall', function () {
+ describe('as an approval', function () {
+ beforeEach(async function () {
+ this.recipient = this.spender;
+ this.approve = (holder, ...rest) =>
+ this.token.connect(holder).getFunction('approveAndCall(address,uint256)')(...rest);
+ });
+
+ shouldBehaveLikeERC20Approve(value);
+ });
+
+ it('reverts approving an EOA', async function () {
+ await expect(this.token.connect(this.holder).getFunction('approveAndCall(address,uint256)')(this.other, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidSpender')
+ .withArgs(this.other.address);
+ });
+
+ it('succeeds without data', async function () {
+ await expect(this.token.connect(this.holder).getFunction('approveAndCall(address,uint256)')(this.spender, value))
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.holder.address, this.spender.target, value)
+ .to.emit(this.spender, 'Approved')
+ .withArgs(this.holder.address, value, '0x');
+ });
+
+ it('succeeds with data', async function () {
+ await expect(
+ this.token.connect(this.holder).getFunction('approveAndCall(address,uint256,bytes)')(this.spender, value, data),
+ )
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.holder.address, this.spender.target, value)
+ .to.emit(this.spender, 'Approved')
+ .withArgs(this.holder.address, value, data);
+ });
+
+ it('with reverting hook (without reason)', async function () {
+ await this.spender.setUp(this.selectors.onApprovalReceived, RevertType.RevertWithoutMessage);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('approveAndCall(address,uint256,bytes)')(this.spender, value, data),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidSpender')
+ .withArgs(this.spender.target);
+ });
+
+ it('reverts with reverting hook (with reason)', async function () {
+ await this.spender.setUp(this.selectors.onApprovalReceived, RevertType.RevertWithMessage);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('approveAndCall(address,uint256,bytes)')(this.spender, value, data),
+ ).to.be.revertedWith('ERC1363SpenderMock: reverting');
+ });
+
+ it('reverts with reverting hook (with custom error)', async function () {
+ const reason = '0x12345678';
+ await this.spender.setUp(reason, RevertType.RevertWithCustomError);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('approveAndCall(address,uint256,bytes)')(this.spender, value, data),
+ )
+ .to.be.revertedWithCustomError(this.spender, 'CustomError')
+ .withArgs(reason);
+ });
+
+ it('panics with reverting hook (with panic)', async function () {
+ await this.spender.setUp(this.selectors.onApprovalReceived, RevertType.Panic);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('approveAndCall(address,uint256,bytes)')(this.spender, value, data),
+ ).to.be.revertedWithPanic();
+ });
+
+ it('reverts with bad return value', async function () {
+ await this.spender.setUp('0x12345678', RevertType.None);
+
+ await expect(
+ this.token.connect(this.holder).getFunction('approveAndCall(address,uint256,bytes)')(this.spender, value, data),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidSpender')
+ .withArgs(this.spender.target);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Burnable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Burnable.test.js
new file mode 100644
index 000000000..dc40c7917
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Burnable.test.js
@@ -0,0 +1,105 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const initialBalance = 1000n;
+
+async function fixture() {
+ const [owner, burner] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC20Burnable', [name, symbol], owner);
+ await token.$_mint(owner, initialBalance);
+
+ return { owner, burner, token, initialBalance };
+}
+
+describe('ERC20Burnable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('burn', function () {
+ it('reverts if not enough balance', async function () {
+ const value = this.initialBalance + 1n;
+
+ await expect(this.token.connect(this.owner).burn(value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.owner, this.initialBalance, value);
+ });
+
+ describe('on success', function () {
+ for (const { title, value } of [
+ { title: 'for a zero value', value: 0n },
+ { title: 'for a non-zero value', value: 100n },
+ ]) {
+ describe(title, function () {
+ beforeEach(async function () {
+ this.tx = await this.token.connect(this.owner).burn(value);
+ });
+
+ it('burns the requested value', async function () {
+ await expect(this.tx).to.changeTokenBalance(this.token, this.owner, -value);
+ });
+
+ it('emits a transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.owner, ethers.ZeroAddress, value);
+ });
+ });
+ }
+ });
+ });
+
+ describe('burnFrom', function () {
+ describe('reverts', function () {
+ it('if not enough balance', async function () {
+ const value = this.initialBalance + 1n;
+
+ await this.token.connect(this.owner).approve(this.burner, value);
+
+ await expect(this.token.connect(this.burner).burnFrom(this.owner, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.owner, this.initialBalance, value);
+ });
+
+ it('if not enough allowance', async function () {
+ const allowance = 100n;
+
+ await this.token.connect(this.owner).approve(this.burner, allowance);
+
+ await expect(this.token.connect(this.burner).burnFrom(this.owner, allowance + 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientAllowance')
+ .withArgs(this.burner, allowance, allowance + 1n);
+ });
+ });
+
+ describe('on success', function () {
+ for (const { title, value } of [
+ { title: 'for a zero value', value: 0n },
+ { title: 'for a non-zero value', value: 100n },
+ ]) {
+ describe(title, function () {
+ const originalAllowance = value * 3n;
+
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.burner, originalAllowance);
+ this.tx = await this.token.connect(this.burner).burnFrom(this.owner, value);
+ });
+
+ it('burns the requested value', async function () {
+ await expect(this.tx).to.changeTokenBalance(this.token, this.owner, -value);
+ });
+
+ it('decrements allowance', async function () {
+ expect(await this.token.allowance(this.owner, this.burner)).to.equal(originalAllowance - value);
+ });
+
+ it('emits a transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.owner, ethers.ZeroAddress, value);
+ });
+ });
+ }
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Capped.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Capped.test.js
new file mode 100644
index 000000000..a32ec43a8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Capped.test.js
@@ -0,0 +1,55 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const cap = 1000n;
+
+async function fixture() {
+ const [user] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC20Capped', [name, symbol, cap]);
+
+ return { user, token, cap };
+}
+
+describe('ERC20Capped', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('requires a non-zero cap', async function () {
+ const ERC20Capped = await ethers.getContractFactory('$ERC20Capped');
+
+ await expect(ERC20Capped.deploy(name, symbol, 0))
+ .to.be.revertedWithCustomError(ERC20Capped, 'ERC20InvalidCap')
+ .withArgs(0);
+ });
+
+ describe('capped token', function () {
+ it('starts with the correct cap', async function () {
+ expect(await this.token.cap()).to.equal(this.cap);
+ });
+
+ it('mints when value is less than cap', async function () {
+ const value = this.cap - 1n;
+ await this.token.$_mint(this.user, value);
+ expect(await this.token.totalSupply()).to.equal(value);
+ });
+
+ it('fails to mint if the value exceeds the cap', async function () {
+ await this.token.$_mint(this.user, this.cap - 1n);
+ await expect(this.token.$_mint(this.user, 2))
+ .to.be.revertedWithCustomError(this.token, 'ERC20ExceededCap')
+ .withArgs(this.cap + 1n, this.cap);
+ });
+
+ it('fails to mint after cap is reached', async function () {
+ await this.token.$_mint(this.user, this.cap);
+ await expect(this.token.$_mint(this.user, 1))
+ .to.be.revertedWithCustomError(this.token, 'ERC20ExceededCap')
+ .withArgs(this.cap + 1n, this.cap);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20FlashMint.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20FlashMint.test.js
new file mode 100644
index 000000000..1c751f74c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20FlashMint.test.js
@@ -0,0 +1,164 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const initialSupply = 100n;
+const loanValue = 10_000_000_000_000n;
+
+async function fixture() {
+ const [holder, other] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC20FlashMintMock', [name, symbol]);
+ await token.$_mint(holder, initialSupply);
+
+ return { holder, other, token };
+}
+
+describe('ERC20FlashMint', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('maxFlashLoan', function () {
+ it('token match', async function () {
+ expect(await this.token.maxFlashLoan(this.token)).to.equal(ethers.MaxUint256 - initialSupply);
+ });
+
+ it('token mismatch', async function () {
+ expect(await this.token.maxFlashLoan(ethers.ZeroAddress)).to.equal(0n);
+ });
+ });
+
+ describe('flashFee', function () {
+ it('token match', async function () {
+ expect(await this.token.flashFee(this.token, loanValue)).to.equal(0n);
+ });
+
+ it('token mismatch', async function () {
+ await expect(this.token.flashFee(ethers.ZeroAddress, loanValue))
+ .to.be.revertedWithCustomError(this.token, 'ERC3156UnsupportedToken')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('flashFeeReceiver', function () {
+ it('default receiver', async function () {
+ expect(await this.token.$_flashFeeReceiver()).to.equal(ethers.ZeroAddress);
+ });
+ });
+
+ describe('flashLoan', function () {
+ it('success', async function () {
+ const receiver = await ethers.deployContract('ERC3156FlashBorrowerMock', [true, true]);
+
+ const tx = await this.token.flashLoan(receiver, this.token, loanValue, '0x');
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, receiver, loanValue)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(receiver, ethers.ZeroAddress, loanValue)
+ .to.emit(receiver, 'BalanceOf')
+ .withArgs(this.token, receiver, loanValue)
+ .to.emit(receiver, 'TotalSupply')
+ .withArgs(this.token, initialSupply + loanValue);
+ await expect(tx).to.changeTokenBalance(this.token, receiver, 0);
+
+ expect(await this.token.totalSupply()).to.equal(initialSupply);
+ expect(await this.token.allowance(receiver, this.token)).to.equal(0n);
+ });
+
+ it('missing return value', async function () {
+ const receiver = await ethers.deployContract('ERC3156FlashBorrowerMock', [false, true]);
+ await expect(this.token.flashLoan(receiver, this.token, loanValue, '0x'))
+ .to.be.revertedWithCustomError(this.token, 'ERC3156InvalidReceiver')
+ .withArgs(receiver);
+ });
+
+ it('missing approval', async function () {
+ const receiver = await ethers.deployContract('ERC3156FlashBorrowerMock', [true, false]);
+ await expect(this.token.flashLoan(receiver, this.token, loanValue, '0x'))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientAllowance')
+ .withArgs(this.token, 0, loanValue);
+ });
+
+ it('unavailable funds', async function () {
+ const receiver = await ethers.deployContract('ERC3156FlashBorrowerMock', [true, true]);
+ const data = this.token.interface.encodeFunctionData('transfer', [this.other.address, 10]);
+ await expect(this.token.flashLoan(receiver, this.token, loanValue, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(receiver, loanValue - 10n, loanValue);
+ });
+
+ it('more than maxFlashLoan', async function () {
+ const receiver = await ethers.deployContract('ERC3156FlashBorrowerMock', [true, true]);
+ const data = this.token.interface.encodeFunctionData('transfer', [this.other.address, 10]);
+ await expect(this.token.flashLoan(receiver, this.token, ethers.MaxUint256, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC3156ExceededMaxLoan')
+ .withArgs(ethers.MaxUint256 - initialSupply);
+ });
+
+ describe('custom flash fee & custom fee receiver', function () {
+ const receiverInitialBalance = 200_000n;
+ const flashFee = 5_000n;
+
+ beforeEach('init receiver balance & set flash fee', async function () {
+ this.receiver = await ethers.deployContract('ERC3156FlashBorrowerMock', [true, true]);
+
+ const tx = await this.token.$_mint(this.receiver, receiverInitialBalance);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.receiver, receiverInitialBalance);
+ await expect(tx).to.changeTokenBalance(this.token, this.receiver, receiverInitialBalance);
+
+ await this.token.setFlashFee(flashFee);
+ expect(await this.token.flashFee(this.token, loanValue)).to.equal(flashFee);
+ });
+
+ it('default flash fee receiver', async function () {
+ const tx = await this.token.flashLoan(this.receiver, this.token, loanValue, '0x');
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.receiver, loanValue)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.receiver, ethers.ZeroAddress, loanValue + flashFee)
+ .to.emit(this.receiver, 'BalanceOf')
+ .withArgs(this.token, this.receiver, receiverInitialBalance + loanValue)
+ .to.emit(this.receiver, 'TotalSupply')
+ .withArgs(this.token, initialSupply + receiverInitialBalance + loanValue);
+ await expect(tx).to.changeTokenBalances(this.token, [this.receiver, ethers.ZeroAddress], [-flashFee, 0]);
+
+ expect(await this.token.totalSupply()).to.equal(initialSupply + receiverInitialBalance - flashFee);
+ expect(await this.token.allowance(this.receiver, this.token)).to.equal(0n);
+ });
+
+ it('custom flash fee receiver', async function () {
+ const flashFeeReceiverAddress = this.other;
+ await this.token.setFlashFeeReceiver(flashFeeReceiverAddress);
+ expect(await this.token.$_flashFeeReceiver()).to.equal(flashFeeReceiverAddress);
+
+ const tx = await this.token.flashLoan(this.receiver, this.token, loanValue, '0x');
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.receiver, loanValue)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.receiver, ethers.ZeroAddress, loanValue)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.receiver, flashFeeReceiverAddress, flashFee)
+ .to.emit(this.receiver, 'BalanceOf')
+ .withArgs(this.token, this.receiver, receiverInitialBalance + loanValue)
+ .to.emit(this.receiver, 'TotalSupply')
+ .withArgs(this.token, initialSupply + receiverInitialBalance + loanValue);
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.receiver, flashFeeReceiverAddress],
+ [-flashFee, flashFee],
+ );
+
+ expect(await this.token.totalSupply()).to.equal(initialSupply + receiverInitialBalance);
+ expect(await this.token.allowance(this.receiver, flashFeeReceiverAddress)).to.equal(0n);
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Pausable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Pausable.test.js
new file mode 100644
index 000000000..1f1157c19
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Pausable.test.js
@@ -0,0 +1,129 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const initialSupply = 100n;
+
+async function fixture() {
+ const [holder, recipient, approved] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC20Pausable', [name, symbol]);
+ await token.$_mint(holder, initialSupply);
+
+ return { holder, recipient, approved, token };
+}
+
+describe('ERC20Pausable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('pausable token', function () {
+ describe('transfer', function () {
+ it('allows to transfer when unpaused', async function () {
+ await expect(this.token.connect(this.holder).transfer(this.recipient, initialSupply)).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.recipient],
+ [-initialSupply, initialSupply],
+ );
+ });
+
+ it('allows to transfer when paused and then unpaused', async function () {
+ await this.token.$_pause();
+ await this.token.$_unpause();
+
+ await expect(this.token.connect(this.holder).transfer(this.recipient, initialSupply)).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.recipient],
+ [-initialSupply, initialSupply],
+ );
+ });
+
+ it('reverts when trying to transfer when paused', async function () {
+ await this.token.$_pause();
+
+ await expect(
+ this.token.connect(this.holder).transfer(this.recipient, initialSupply),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+ });
+
+ describe('transfer from', function () {
+ const allowance = 40n;
+
+ beforeEach(async function () {
+ await this.token.connect(this.holder).approve(this.approved, allowance);
+ });
+
+ it('allows to transfer from when unpaused', async function () {
+ await expect(
+ this.token.connect(this.approved).transferFrom(this.holder, this.recipient, allowance),
+ ).to.changeTokenBalances(this.token, [this.holder, this.recipient], [-allowance, allowance]);
+ });
+
+ it('allows to transfer when paused and then unpaused', async function () {
+ await this.token.$_pause();
+ await this.token.$_unpause();
+
+ await expect(
+ this.token.connect(this.approved).transferFrom(this.holder, this.recipient, allowance),
+ ).to.changeTokenBalances(this.token, [this.holder, this.recipient], [-allowance, allowance]);
+ });
+
+ it('reverts when trying to transfer from when paused', async function () {
+ await this.token.$_pause();
+
+ await expect(
+ this.token.connect(this.approved).transferFrom(this.holder, this.recipient, allowance),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+ });
+
+ describe('mint', function () {
+ const value = 42n;
+
+ it('allows to mint when unpaused', async function () {
+ await expect(this.token.$_mint(this.recipient, value)).to.changeTokenBalance(this.token, this.recipient, value);
+ });
+
+ it('allows to mint when paused and then unpaused', async function () {
+ await this.token.$_pause();
+ await this.token.$_unpause();
+
+ await expect(this.token.$_mint(this.recipient, value)).to.changeTokenBalance(this.token, this.recipient, value);
+ });
+
+ it('reverts when trying to mint when paused', async function () {
+ await this.token.$_pause();
+
+ await expect(this.token.$_mint(this.recipient, value)).to.be.revertedWithCustomError(
+ this.token,
+ 'EnforcedPause',
+ );
+ });
+ });
+
+ describe('burn', function () {
+ const value = 42n;
+
+ it('allows to burn when unpaused', async function () {
+ await expect(this.token.$_burn(this.holder, value)).to.changeTokenBalance(this.token, this.holder, -value);
+ });
+
+ it('allows to burn when paused and then unpaused', async function () {
+ await this.token.$_pause();
+ await this.token.$_unpause();
+
+ await expect(this.token.$_burn(this.holder, value)).to.changeTokenBalance(this.token, this.holder, -value);
+ });
+
+ it('reverts when trying to burn when paused', async function () {
+ await this.token.$_pause();
+
+ await expect(this.token.$_burn(this.holder, value)).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Permit.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Permit.test.js
new file mode 100644
index 000000000..c3c80d7bb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Permit.test.js
@@ -0,0 +1,109 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getDomain, domainSeparator, Permit } = require('../../../helpers/eip712');
+const time = require('../../../helpers/time');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const initialSupply = 100n;
+
+async function fixture() {
+ const [holder, spender, owner, other] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC20Permit', [name, symbol, name]);
+ await token.$_mint(holder, initialSupply);
+
+ return {
+ holder,
+ spender,
+ owner,
+ other,
+ token,
+ };
+}
+
+describe('ERC20Permit', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('initial nonce is 0', async function () {
+ expect(await this.token.nonces(this.holder)).to.equal(0n);
+ });
+
+ it('domain separator', async function () {
+ expect(await this.token.DOMAIN_SEPARATOR()).to.equal(await getDomain(this.token).then(domainSeparator));
+ });
+
+ describe('permit', function () {
+ const value = 42n;
+ const nonce = 0n;
+ const maxDeadline = ethers.MaxUint256;
+
+ beforeEach(function () {
+ this.buildData = (contract, deadline = maxDeadline) =>
+ getDomain(contract).then(domain => ({
+ domain,
+ types: { Permit },
+ message: {
+ owner: this.owner.address,
+ spender: this.spender.address,
+ value,
+ nonce,
+ deadline,
+ },
+ }));
+ });
+
+ it('accepts owner signature', async function () {
+ const { v, r, s } = await this.buildData(this.token)
+ .then(({ domain, types, message }) => this.owner.signTypedData(domain, types, message))
+ .then(ethers.Signature.from);
+
+ await this.token.permit(this.owner, this.spender, value, maxDeadline, v, r, s);
+
+ expect(await this.token.nonces(this.owner)).to.equal(1n);
+ expect(await this.token.allowance(this.owner, this.spender)).to.equal(value);
+ });
+
+ it('rejects reused signature', async function () {
+ const { v, r, s, serialized } = await this.buildData(this.token)
+ .then(({ domain, types, message }) => this.owner.signTypedData(domain, types, message))
+ .then(ethers.Signature.from);
+
+ await this.token.permit(this.owner, this.spender, value, maxDeadline, v, r, s);
+
+ const recovered = await this.buildData(this.token).then(({ domain, types, message }) =>
+ ethers.verifyTypedData(domain, types, { ...message, nonce: nonce + 1n, deadline: maxDeadline }, serialized),
+ );
+
+ await expect(this.token.permit(this.owner, this.spender, value, maxDeadline, v, r, s))
+ .to.be.revertedWithCustomError(this.token, 'ERC2612InvalidSigner')
+ .withArgs(recovered, this.owner);
+ });
+
+ it('rejects other signature', async function () {
+ const { v, r, s } = await this.buildData(this.token)
+ .then(({ domain, types, message }) => this.other.signTypedData(domain, types, message))
+ .then(ethers.Signature.from);
+
+ await expect(this.token.permit(this.owner, this.spender, value, maxDeadline, v, r, s))
+ .to.be.revertedWithCustomError(this.token, 'ERC2612InvalidSigner')
+ .withArgs(this.other, this.owner);
+ });
+
+ it('rejects expired permit', async function () {
+ const deadline = (await time.clock.timestamp()) - time.duration.weeks(1);
+
+ const { v, r, s } = await this.buildData(this.token, deadline)
+ .then(({ domain, types, message }) => this.owner.signTypedData(domain, types, message))
+ .then(ethers.Signature.from);
+
+ await expect(this.token.permit(this.owner, this.spender, value, deadline, v, r, s))
+ .to.be.revertedWithCustomError(this.token, 'ERC2612ExpiredSignature')
+ .withArgs(deadline);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Votes.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Votes.test.js
new file mode 100644
index 000000000..3c595c919
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Votes.test.js
@@ -0,0 +1,546 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getDomain, Delegation } = require('../../../helpers/eip712');
+const { batchInBlock } = require('../../../helpers/txpool');
+const time = require('../../../helpers/time');
+
+const { shouldBehaveLikeVotes } = require('../../../governance/utils/Votes.behavior');
+
+const TOKENS = [
+ { Token: '$ERC20Votes', mode: 'blocknumber' },
+ { Token: '$ERC20VotesTimestampMock', mode: 'timestamp' },
+];
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const version = '1';
+const supply = ethers.parseEther('10000000');
+
+describe('ERC20Votes', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ // accounts is required by shouldBehaveLikeVotes
+ const accounts = await ethers.getSigners();
+ const [holder, recipient, delegatee, other1, other2] = accounts;
+
+ const token = await ethers.deployContract(Token, [name, symbol, name, version]);
+ const domain = await getDomain(token);
+
+ return { accounts, holder, recipient, delegatee, other1, other2, token, domain };
+ };
+
+ describe(`vote with ${mode}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ this.votes = this.token;
+ });
+
+ // includes ERC6372 behavior check
+ shouldBehaveLikeVotes([1, 17, 42], { mode, fungible: true });
+
+ it('initial nonce is 0', async function () {
+ expect(await this.token.nonces(this.holder)).to.equal(0n);
+ });
+
+ it('minting restriction', async function () {
+ const value = 2n ** 208n;
+ await expect(this.token.$_mint(this.holder, value))
+ .to.be.revertedWithCustomError(this.token, 'ERC20ExceededSafeSupply')
+ .withArgs(value, value - 1n);
+ });
+
+ it('recent checkpoints', async function () {
+ await this.token.connect(this.holder).delegate(this.holder);
+ for (let i = 0; i < 6; i++) {
+ await this.token.$_mint(this.holder, 1n);
+ }
+ const timepoint = await time.clock[mode]();
+ expect(await this.token.numCheckpoints(this.holder)).to.equal(6n);
+ // recent
+ expect(await this.token.getPastVotes(this.holder, timepoint - 1n)).to.equal(5n);
+ // non-recent
+ expect(await this.token.getPastVotes(this.holder, timepoint - 6n)).to.equal(0n);
+ });
+
+ describe('set delegation', function () {
+ describe('call', function () {
+ it('delegation with balance', async function () {
+ await this.token.$_mint(this.holder, supply);
+ expect(await this.token.delegates(this.holder)).to.equal(ethers.ZeroAddress);
+
+ const tx = await this.token.connect(this.holder).delegate(this.holder);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(tx)
+ .to.emit(this.token, 'DelegateChanged')
+ .withArgs(this.holder, ethers.ZeroAddress, this.holder)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, 0n, supply);
+
+ expect(await this.token.delegates(this.holder)).to.equal(this.holder);
+ expect(await this.token.getVotes(this.holder)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.holder, timepoint - 1n)).to.equal(0n);
+ await mine();
+ expect(await this.token.getPastVotes(this.holder, timepoint)).to.equal(supply);
+ });
+
+ it('delegation without balance', async function () {
+ expect(await this.token.delegates(this.holder)).to.equal(ethers.ZeroAddress);
+
+ await expect(this.token.connect(this.holder).delegate(this.holder))
+ .to.emit(this.token, 'DelegateChanged')
+ .withArgs(this.holder, ethers.ZeroAddress, this.holder)
+ .to.not.emit(this.token, 'DelegateVotesChanged');
+
+ expect(await this.token.delegates(this.holder)).to.equal(this.holder);
+ });
+ });
+
+ describe('with signature', function () {
+ const nonce = 0n;
+
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, supply);
+ });
+
+ it('accept signed delegation', async function () {
+ const { r, s, v } = await this.holder
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.holder.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ expect(await this.token.delegates(this.holder)).to.equal(ethers.ZeroAddress);
+
+ const tx = await this.token.delegateBySig(this.holder, nonce, ethers.MaxUint256, v, r, s);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(tx)
+ .to.emit(this.token, 'DelegateChanged')
+ .withArgs(this.holder, ethers.ZeroAddress, this.holder)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, 0n, supply);
+
+ expect(await this.token.delegates(this.holder)).to.equal(this.holder);
+
+ expect(await this.token.getVotes(this.holder)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.holder, timepoint - 1n)).to.equal(0n);
+ await mine();
+ expect(await this.token.getPastVotes(this.holder, timepoint)).to.equal(supply);
+ });
+
+ it('rejects reused signature', async function () {
+ const { r, s, v } = await this.holder
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.holder.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ await this.token.delegateBySig(this.holder, nonce, ethers.MaxUint256, v, r, s);
+
+ await expect(this.token.delegateBySig(this.holder, nonce, ethers.MaxUint256, v, r, s))
+ .to.be.revertedWithCustomError(this.token, 'InvalidAccountNonce')
+ .withArgs(this.holder, nonce + 1n);
+ });
+
+ it('rejects bad delegatee', async function () {
+ const { r, s, v } = await this.holder
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.holder.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ const tx = await this.token.delegateBySig(this.delegatee, nonce, ethers.MaxUint256, v, r, s);
+
+ const { args } = await tx
+ .wait()
+ .then(receipt => receipt.logs.find(event => event.fragment.name == 'DelegateChanged'));
+ expect(args[0]).to.not.equal(this.holder);
+ expect(args[1]).to.equal(ethers.ZeroAddress);
+ expect(args[2]).to.equal(this.delegatee);
+ });
+
+ it('rejects bad nonce', async function () {
+ const { r, s, v, serialized } = await this.holder
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.holder.address,
+ nonce,
+ expiry: ethers.MaxUint256,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ const recovered = ethers.verifyTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.holder.address,
+ nonce: nonce + 1n,
+ expiry: ethers.MaxUint256,
+ },
+ serialized,
+ );
+
+ await expect(this.token.delegateBySig(this.holder, nonce + 1n, ethers.MaxUint256, v, r, s))
+ .to.be.revertedWithCustomError(this.token, 'InvalidAccountNonce')
+ .withArgs(recovered, nonce);
+ });
+
+ it('rejects expired permit', async function () {
+ const expiry = (await time.clock.timestamp()) - time.duration.weeks(1);
+
+ const { r, s, v } = await this.holder
+ .signTypedData(
+ this.domain,
+ { Delegation },
+ {
+ delegatee: this.holder.address,
+ nonce,
+ expiry,
+ },
+ )
+ .then(ethers.Signature.from);
+
+ await expect(this.token.delegateBySig(this.holder, nonce, expiry, v, r, s))
+ .to.be.revertedWithCustomError(this.token, 'VotesExpiredSignature')
+ .withArgs(expiry);
+ });
+ });
+ });
+
+ describe('change delegation', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, supply);
+ await this.token.connect(this.holder).delegate(this.holder);
+ });
+
+ it('call', async function () {
+ expect(await this.token.delegates(this.holder)).to.equal(this.holder);
+
+ const tx = await this.token.connect(this.holder).delegate(this.delegatee);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await expect(tx)
+ .to.emit(this.token, 'DelegateChanged')
+ .withArgs(this.holder, this.holder, this.delegatee)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, supply, 0n)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.delegatee, 0n, supply);
+
+ expect(await this.token.delegates(this.holder)).to.equal(this.delegatee);
+
+ expect(await this.token.getVotes(this.holder)).to.equal(0n);
+ expect(await this.token.getVotes(this.delegatee)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.holder, timepoint - 1n)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.delegatee, timepoint - 1n)).to.equal(0n);
+ await mine();
+ expect(await this.token.getPastVotes(this.holder, timepoint)).to.equal(0n);
+ expect(await this.token.getPastVotes(this.delegatee, timepoint)).to.equal(supply);
+ });
+ });
+
+ describe('transfers', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, supply);
+ });
+
+ it('no delegation', async function () {
+ await expect(this.token.connect(this.holder).transfer(this.recipient, 1n))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, 1n)
+ .to.not.emit(this.token, 'DelegateVotesChanged');
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 0n;
+ });
+
+ it('sender delegation', async function () {
+ await this.token.connect(this.holder).delegate(this.holder);
+
+ const tx = await this.token.connect(this.holder).transfer(this.recipient, 1n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, 1n)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, supply, supply - 1n);
+
+ const { logs } = await tx.wait();
+ const { index } = logs.find(event => event.fragment.name == 'DelegateVotesChanged');
+ for (const event of logs.filter(event => event.fragment.name == 'Transfer')) {
+ expect(event.index).to.lt(index);
+ }
+
+ this.holderVotes = supply - 1n;
+ this.recipientVotes = 0n;
+ });
+
+ it('receiver delegation', async function () {
+ await this.token.connect(this.recipient).delegate(this.recipient);
+
+ const tx = await this.token.connect(this.holder).transfer(this.recipient, 1n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, 1n)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.recipient, 0n, 1n);
+
+ const { logs } = await tx.wait();
+ const { index } = logs.find(event => event.fragment.name == 'DelegateVotesChanged');
+ for (const event of logs.filter(event => event.fragment.name == 'Transfer')) {
+ expect(event.index).to.lt(index);
+ }
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 1n;
+ });
+
+ it('full delegation', async function () {
+ await this.token.connect(this.holder).delegate(this.holder);
+ await this.token.connect(this.recipient).delegate(this.recipient);
+
+ const tx = await this.token.connect(this.holder).transfer(this.recipient, 1n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, 1n)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, supply, supply - 1n)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.recipient, 0n, 1n);
+
+ const { logs } = await tx.wait();
+ const { index } = logs.find(event => event.fragment.name == 'DelegateVotesChanged');
+ for (const event of logs.filter(event => event.fragment.name == 'Transfer')) {
+ expect(event.index).to.lt(index);
+ }
+
+ this.holderVotes = supply - 1n;
+ this.recipientVotes = 1n;
+ });
+
+ afterEach(async function () {
+ expect(await this.token.getVotes(this.holder)).to.equal(this.holderVotes);
+ expect(await this.token.getVotes(this.recipient)).to.equal(this.recipientVotes);
+
+ // need to advance 2 blocks to see the effect of a transfer on "getPastVotes"
+ const timepoint = await time.clock[mode]();
+ await mine();
+ expect(await this.token.getPastVotes(this.holder, timepoint)).to.equal(this.holderVotes);
+ expect(await this.token.getPastVotes(this.recipient, timepoint)).to.equal(this.recipientVotes);
+ });
+ });
+
+ // The following tests are a adaptation of https://github.com/compound-finance/compound-protocol/blob/master/tests/Governance/CompTest.js.
+ describe('Compound test suite', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.holder, supply);
+ });
+
+ describe('balanceOf', function () {
+ it('grants to initial account', async function () {
+ expect(await this.token.balanceOf(this.holder)).to.equal(supply);
+ });
+ });
+
+ describe('numCheckpoints', function () {
+ it('returns the number of checkpoints for a delegate', async function () {
+ await this.token.connect(this.holder).transfer(this.recipient, 100n); //give an account a few tokens for readability
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(0n);
+
+ const t1 = await this.token.connect(this.recipient).delegate(this.other1);
+ t1.timepoint = await time.clockFromReceipt[mode](t1);
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(1n);
+
+ const t2 = await this.token.connect(this.recipient).transfer(this.other2, 10);
+ t2.timepoint = await time.clockFromReceipt[mode](t2);
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(2n);
+
+ const t3 = await this.token.connect(this.recipient).transfer(this.other2, 10);
+ t3.timepoint = await time.clockFromReceipt[mode](t3);
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(3n);
+
+ const t4 = await this.token.connect(this.holder).transfer(this.recipient, 20);
+ t4.timepoint = await time.clockFromReceipt[mode](t4);
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(4n);
+
+ expect(await this.token.checkpoints(this.other1, 0n)).to.deep.equal([t1.timepoint, 100n]);
+ expect(await this.token.checkpoints(this.other1, 1n)).to.deep.equal([t2.timepoint, 90n]);
+ expect(await this.token.checkpoints(this.other1, 2n)).to.deep.equal([t3.timepoint, 80n]);
+ expect(await this.token.checkpoints(this.other1, 3n)).to.deep.equal([t4.timepoint, 100n]);
+ await mine();
+ expect(await this.token.getPastVotes(this.other1, t1.timepoint)).to.equal(100n);
+ expect(await this.token.getPastVotes(this.other1, t2.timepoint)).to.equal(90n);
+ expect(await this.token.getPastVotes(this.other1, t3.timepoint)).to.equal(80n);
+ expect(await this.token.getPastVotes(this.other1, t4.timepoint)).to.equal(100n);
+ });
+
+ it('does not add more than one checkpoint in a block', async function () {
+ await this.token.connect(this.holder).transfer(this.recipient, 100n);
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(0n);
+
+ const [t1, t2, t3] = await batchInBlock([
+ () => this.token.connect(this.recipient).delegate(this.other1, { gasLimit: 200000 }),
+ () => this.token.connect(this.recipient).transfer(this.other2, 10n, { gasLimit: 200000 }),
+ () => this.token.connect(this.recipient).transfer(this.other2, 10n, { gasLimit: 200000 }),
+ ]);
+ t1.timepoint = await time.clockFromReceipt[mode](t1);
+ t2.timepoint = await time.clockFromReceipt[mode](t2);
+ t3.timepoint = await time.clockFromReceipt[mode](t3);
+
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(1);
+ expect(await this.token.checkpoints(this.other1, 0n)).to.be.deep.equal([t1.timepoint, 80n]);
+
+ const t4 = await this.token.connect(this.holder).transfer(this.recipient, 20n);
+ t4.timepoint = await time.clockFromReceipt[mode](t4);
+
+ expect(await this.token.numCheckpoints(this.other1)).to.equal(2n);
+ expect(await this.token.checkpoints(this.other1, 1n)).to.be.deep.equal([t4.timepoint, 100n]);
+ });
+ });
+
+ describe('getPastVotes', function () {
+ it('reverts if block number >= current block', async function () {
+ const clock = await this.token.clock();
+ await expect(this.token.getPastVotes(this.other1, 50_000_000_000n))
+ .to.be.revertedWithCustomError(this.token, 'ERC5805FutureLookup')
+ .withArgs(50_000_000_000n, clock);
+ });
+
+ it('returns 0 if there are no checkpoints', async function () {
+ expect(await this.token.getPastVotes(this.other1, 0n)).to.equal(0n);
+ });
+
+ it('returns the latest block if >= last checkpoint block', async function () {
+ const tx = await this.token.connect(this.holder).delegate(this.other1);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+ await mine(2);
+
+ expect(await this.token.getPastVotes(this.other1, timepoint)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.other1, timepoint + 1n)).to.equal(supply);
+ });
+
+ it('returns zero if < first checkpoint block', async function () {
+ await mine();
+ const tx = await this.token.connect(this.holder).delegate(this.other1);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+ await mine(2);
+
+ expect(await this.token.getPastVotes(this.other1, timepoint - 1n)).to.equal(0n);
+ expect(await this.token.getPastVotes(this.other1, timepoint + 1n)).to.equal(supply);
+ });
+
+ it('generally returns the voting balance at the appropriate checkpoint', async function () {
+ const t1 = await this.token.connect(this.holder).delegate(this.other1);
+ await mine(2);
+ const t2 = await this.token.connect(this.holder).transfer(this.other2, 10);
+ await mine(2);
+ const t3 = await this.token.connect(this.holder).transfer(this.other2, 10);
+ await mine(2);
+ const t4 = await this.token.connect(this.other2).transfer(this.holder, 20);
+ await mine(2);
+
+ t1.timepoint = await time.clockFromReceipt[mode](t1);
+ t2.timepoint = await time.clockFromReceipt[mode](t2);
+ t3.timepoint = await time.clockFromReceipt[mode](t3);
+ t4.timepoint = await time.clockFromReceipt[mode](t4);
+
+ expect(await this.token.getPastVotes(this.other1, t1.timepoint - 1n)).to.equal(0n);
+ expect(await this.token.getPastVotes(this.other1, t1.timepoint)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.other1, t1.timepoint + 1n)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.other1, t2.timepoint)).to.equal(supply - 10n);
+ expect(await this.token.getPastVotes(this.other1, t2.timepoint + 1n)).to.equal(supply - 10n);
+ expect(await this.token.getPastVotes(this.other1, t3.timepoint)).to.equal(supply - 20n);
+ expect(await this.token.getPastVotes(this.other1, t3.timepoint + 1n)).to.equal(supply - 20n);
+ expect(await this.token.getPastVotes(this.other1, t4.timepoint)).to.equal(supply);
+ expect(await this.token.getPastVotes(this.other1, t4.timepoint + 1n)).to.equal(supply);
+ });
+ });
+ });
+
+ describe('getPastTotalSupply', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).delegate(this.holder);
+ });
+
+ it('reverts if block number >= current block', async function () {
+ const clock = await this.token.clock();
+ await expect(this.token.getPastTotalSupply(50_000_000_000n))
+ .to.be.revertedWithCustomError(this.token, 'ERC5805FutureLookup')
+ .withArgs(50_000_000_000n, clock);
+ });
+
+ it('returns 0 if there are no checkpoints', async function () {
+ expect(await this.token.getPastTotalSupply(0n)).to.equal(0n);
+ });
+
+ it('returns the latest block if >= last checkpoint block', async function () {
+ const tx = await this.token.$_mint(this.holder, supply);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+ await mine(2);
+
+ expect(await this.token.getPastTotalSupply(timepoint)).to.equal(supply);
+ expect(await this.token.getPastTotalSupply(timepoint + 1n)).to.equal(supply);
+ });
+
+ it('returns zero if < first checkpoint block', async function () {
+ await mine();
+ const tx = await this.token.$_mint(this.holder, supply);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+ await mine(2);
+
+ expect(await this.token.getPastTotalSupply(timepoint - 1n)).to.equal(0n);
+ expect(await this.token.getPastTotalSupply(timepoint + 1n)).to.equal(supply);
+ });
+
+ it('generally returns the voting balance at the appropriate checkpoint', async function () {
+ const t1 = await this.token.$_mint(this.holder, supply);
+ await mine(2);
+ const t2 = await this.token.$_burn(this.holder, 10n);
+ await mine(2);
+ const t3 = await this.token.$_burn(this.holder, 10n);
+ await mine(2);
+ const t4 = await this.token.$_mint(this.holder, 20n);
+ await mine(2);
+
+ t1.timepoint = await time.clockFromReceipt[mode](t1);
+ t2.timepoint = await time.clockFromReceipt[mode](t2);
+ t3.timepoint = await time.clockFromReceipt[mode](t3);
+ t4.timepoint = await time.clockFromReceipt[mode](t4);
+
+ expect(await this.token.getPastTotalSupply(t1.timepoint - 1n)).to.equal(0n);
+ expect(await this.token.getPastTotalSupply(t1.timepoint)).to.equal(supply);
+ expect(await this.token.getPastTotalSupply(t1.timepoint + 1n)).to.equal(supply);
+ expect(await this.token.getPastTotalSupply(t2.timepoint)).to.equal(supply - 10n);
+ expect(await this.token.getPastTotalSupply(t2.timepoint + 1n)).to.equal(supply - 10n);
+ expect(await this.token.getPastTotalSupply(t3.timepoint)).to.equal(supply - 20n);
+ expect(await this.token.getPastTotalSupply(t3.timepoint + 1n)).to.equal(supply - 20n);
+ expect(await this.token.getPastTotalSupply(t4.timepoint)).to.equal(supply);
+ expect(await this.token.getPastTotalSupply(t4.timepoint + 1n)).to.equal(supply);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Wrapper.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Wrapper.test.js
new file mode 100644
index 000000000..9e72e1a92
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC20Wrapper.test.js
@@ -0,0 +1,203 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldBehaveLikeERC20 } = require('../ERC20.behavior');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const decimals = 9n;
+const initialSupply = 100n;
+
+async function fixture() {
+ // this.accounts is used by shouldBehaveLikeERC20
+ const accounts = await ethers.getSigners();
+ const [holder, recipient, other] = accounts;
+
+ const underlying = await ethers.deployContract('$ERC20DecimalsMock', [name, symbol, decimals]);
+ await underlying.$_mint(holder, initialSupply);
+
+ const token = await ethers.deployContract('$ERC20Wrapper', [`Wrapped ${name}`, `W${symbol}`, underlying]);
+
+ return { accounts, holder, recipient, other, underlying, token };
+}
+
+describe('ERC20Wrapper', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ afterEach('Underlying balance', async function () {
+ expect(await this.underlying.balanceOf(this.token)).to.equal(await this.token.totalSupply());
+ });
+
+ it('has a name', async function () {
+ expect(await this.token.name()).to.equal(`Wrapped ${name}`);
+ });
+
+ it('has a symbol', async function () {
+ expect(await this.token.symbol()).to.equal(`W${symbol}`);
+ });
+
+ it('has the same decimals as the underlying token', async function () {
+ expect(await this.token.decimals()).to.equal(decimals);
+ });
+
+ it('decimals default back to 18 if token has no metadata', async function () {
+ const noDecimals = await ethers.deployContract('CallReceiverMock');
+ const token = await ethers.deployContract('$ERC20Wrapper', [`Wrapped ${name}`, `W${symbol}`, noDecimals]);
+ expect(await token.decimals()).to.equal(18n);
+ });
+
+ it('has underlying', async function () {
+ expect(await this.token.underlying()).to.equal(this.underlying);
+ });
+
+ describe('deposit', function () {
+ it('executes with approval', async function () {
+ await this.underlying.connect(this.holder).approve(this.token, initialSupply);
+
+ const tx = await this.token.connect(this.holder).depositFor(this.holder, initialSupply);
+ await expect(tx)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.holder, this.token, initialSupply)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.holder, initialSupply);
+ await expect(tx).to.changeTokenBalances(
+ this.underlying,
+ [this.holder, this.token],
+ [-initialSupply, initialSupply],
+ );
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, initialSupply);
+ });
+
+ it('reverts when missing approval', async function () {
+ await expect(this.token.connect(this.holder).depositFor(this.holder, initialSupply))
+ .to.be.revertedWithCustomError(this.underlying, 'ERC20InsufficientAllowance')
+ .withArgs(this.token, 0, initialSupply);
+ });
+
+ it('reverts when inssuficient balance', async function () {
+ await this.underlying.connect(this.holder).approve(this.token, ethers.MaxUint256);
+
+ await expect(this.token.connect(this.holder).depositFor(this.holder, ethers.MaxUint256))
+ .to.be.revertedWithCustomError(this.underlying, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, initialSupply, ethers.MaxUint256);
+ });
+
+ it('deposits to other account', async function () {
+ await this.underlying.connect(this.holder).approve(this.token, initialSupply);
+
+ const tx = await this.token.connect(this.holder).depositFor(this.recipient, initialSupply);
+ await expect(tx)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.holder, this.token.target, initialSupply)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, initialSupply);
+ await expect(tx).to.changeTokenBalances(
+ this.underlying,
+ [this.holder, this.token],
+ [-initialSupply, initialSupply],
+ );
+ await expect(tx).to.changeTokenBalances(this.token, [this.holder, this.recipient], [0, initialSupply]);
+ });
+
+ it('reverts minting to the wrapper contract', async function () {
+ await this.underlying.connect(this.holder).approve(this.token, ethers.MaxUint256);
+
+ await expect(this.token.connect(this.holder).depositFor(this.token, ethers.MaxUint256))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidReceiver')
+ .withArgs(this.token);
+ });
+ });
+
+ describe('withdraw', function () {
+ beforeEach(async function () {
+ await this.underlying.connect(this.holder).approve(this.token, initialSupply);
+ await this.token.connect(this.holder).depositFor(this.holder, initialSupply);
+ });
+
+ it('reverts when inssuficient balance', async function () {
+ await expect(this.token.connect(this.holder).withdrawTo(this.holder, ethers.MaxInt256))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, initialSupply, ethers.MaxInt256);
+ });
+
+ it('executes when operation is valid', async function () {
+ const value = 42n;
+
+ const tx = await this.token.connect(this.holder).withdrawTo(this.holder, value);
+ await expect(tx)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token.target, this.holder, value)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, value);
+ await expect(tx).to.changeTokenBalances(this.underlying, [this.token, this.holder], [-value, value]);
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, -value);
+ });
+
+ it('entire balance', async function () {
+ const tx = await this.token.connect(this.holder).withdrawTo(this.holder, initialSupply);
+ await expect(tx)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token.target, this.holder, initialSupply)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, initialSupply);
+ await expect(tx).to.changeTokenBalances(
+ this.underlying,
+ [this.token, this.holder],
+ [-initialSupply, initialSupply],
+ );
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, -initialSupply);
+ });
+
+ it('to other account', async function () {
+ const tx = await this.token.connect(this.holder).withdrawTo(this.recipient, initialSupply);
+ await expect(tx)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.recipient, initialSupply)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, initialSupply);
+ await expect(tx).to.changeTokenBalances(
+ this.underlying,
+ [this.token, this.holder, this.recipient],
+ [-initialSupply, 0, initialSupply],
+ );
+ await expect(tx).to.changeTokenBalance(this.token, this.holder, -initialSupply);
+ });
+
+ it('reverts withdrawing to the wrapper contract', async function () {
+ await expect(this.token.connect(this.holder).withdrawTo(this.token, initialSupply))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidReceiver')
+ .withArgs(this.token);
+ });
+ });
+
+ describe('recover', function () {
+ it('nothing to recover', async function () {
+ await this.underlying.connect(this.holder).approve(this.token, initialSupply);
+ await this.token.connect(this.holder).depositFor(this.holder, initialSupply);
+
+ const tx = await this.token.$_recover(this.recipient);
+ await expect(tx).to.emit(this.token, 'Transfer').withArgs(ethers.ZeroAddress, this.recipient, 0n);
+ await expect(tx).to.changeTokenBalance(this.token, this.recipient, 0);
+ });
+
+ it('something to recover', async function () {
+ await this.underlying.connect(this.holder).transfer(this.token, initialSupply);
+
+ const tx = await this.token.$_recover(this.recipient);
+ await expect(tx).to.emit(this.token, 'Transfer').withArgs(ethers.ZeroAddress, this.recipient, initialSupply);
+ await expect(tx).to.changeTokenBalance(this.token, this.recipient, initialSupply);
+ });
+ });
+
+ describe('erc20 behaviour', function () {
+ beforeEach(async function () {
+ await this.underlying.connect(this.holder).approve(this.token, initialSupply);
+ await this.token.connect(this.holder).depositFor(this.holder, initialSupply);
+ });
+
+ shouldBehaveLikeERC20(initialSupply);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.t.sol
new file mode 100644
index 000000000..72b0daca1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.t.sol
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.20;
+
+import {ERC4626Test} from "erc4626-tests/ERC4626.test.sol";
+
+import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+import {ERC4626} from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";
+
+import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol";
+import {ERC4626Mock} from "@openzeppelin/contracts/mocks/token/ERC4626Mock.sol";
+import {ERC4626OffsetMock} from "@openzeppelin/contracts/mocks/token/ERC4626OffsetMock.sol";
+
+contract ERC4626VaultOffsetMock is ERC4626OffsetMock {
+ constructor(
+ ERC20 underlying_,
+ uint8 offset_
+ ) ERC20("My Token Vault", "MTKNV") ERC4626(underlying_) ERC4626OffsetMock(offset_) {}
+}
+
+contract ERC4626StdTest is ERC4626Test {
+ ERC20 private _underlying = new ERC20Mock();
+
+ function setUp() public override {
+ _underlying_ = address(_underlying);
+ _vault_ = address(new ERC4626Mock(_underlying_));
+ _delta_ = 0;
+ _vaultMayBeEmpty = true;
+ _unlimitedAmount = true;
+ }
+
+ /**
+ * @dev Check the case where calculated `decimals` value overflows the `uint8` type.
+ */
+ function testFuzzDecimalsOverflow(uint8 offset) public {
+ /// @dev Remember that the `_underlying` exhibits a `decimals` value of 18.
+ offset = uint8(bound(uint256(offset), 238, uint256(type(uint8).max)));
+ ERC4626VaultOffsetMock erc4626VaultOffsetMock = new ERC4626VaultOffsetMock(_underlying, offset);
+ vm.expectRevert();
+ erc4626VaultOffsetMock.decimals();
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.test.js
new file mode 100644
index 000000000..71c7cbaaf
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/ERC4626.test.js
@@ -0,0 +1,888 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { Enum } = require('../../../helpers/enums');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const decimals = 18n;
+
+async function fixture() {
+ const [holder, recipient, spender, other, ...accounts] = await ethers.getSigners();
+ return { holder, recipient, spender, other, accounts };
+}
+
+describe('ERC4626', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('inherit decimals if from asset', async function () {
+ for (const decimals of [0n, 9n, 12n, 18n, 36n]) {
+ const token = await ethers.deployContract('$ERC20DecimalsMock', ['', '', decimals]);
+ const vault = await ethers.deployContract('$ERC4626', ['', '', token]);
+ expect(await vault.decimals()).to.equal(decimals);
+ }
+ });
+
+ it('asset has not yet been created', async function () {
+ const vault = await ethers.deployContract('$ERC4626', ['', '', this.other.address]);
+ expect(await vault.decimals()).to.equal(decimals);
+ });
+
+ it('underlying excess decimals', async function () {
+ const token = await ethers.deployContract('$ERC20ExcessDecimalsMock');
+ const vault = await ethers.deployContract('$ERC4626', ['', '', token]);
+ expect(await vault.decimals()).to.equal(decimals);
+ });
+
+ it('decimals overflow', async function () {
+ for (const offset of [243n, 250n, 255n]) {
+ const token = await ethers.deployContract('$ERC20DecimalsMock', ['', '', decimals]);
+ const vault = await ethers.deployContract('$ERC4626OffsetMock', ['', '', token, offset]);
+ await expect(vault.decimals()).to.be.revertedWithPanic(PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW);
+ }
+ });
+
+ describe('reentrancy', function () {
+ const reenterType = Enum('No', 'Before', 'After');
+
+ const value = 1_000_000_000_000_000_000n;
+ const reenterValue = 1_000_000_000n;
+
+ beforeEach(async function () {
+ // Use offset 1 so the rate is not 1:1 and we can't possibly confuse assets and shares
+ const token = await ethers.deployContract('$ERC20Reentrant');
+ const vault = await ethers.deployContract('$ERC4626OffsetMock', ['', '', token, 1n]);
+ // Funds and approval for tests
+ await token.$_mint(this.holder, value);
+ await token.$_mint(this.other, value);
+ await token.$_approve(this.holder, vault, ethers.MaxUint256);
+ await token.$_approve(this.other, vault, ethers.MaxUint256);
+ await token.$_approve(token, vault, ethers.MaxUint256);
+
+ Object.assign(this, { token, vault });
+ });
+
+ // During a `_deposit`, the vault does `transferFrom(depositor, vault, assets)` -> `_mint(receiver, shares)`
+ // such that a reentrancy BEFORE the transfer guarantees the price is kept the same.
+ // If the order of transfer -> mint is changed to mint -> transfer, the reentrancy could be triggered on an
+ // intermediate state in which the ratio of assets/shares has been decreased (more shares than assets).
+ it('correct share price is observed during reentrancy before deposit', async function () {
+ // mint token for deposit
+ await this.token.$_mint(this.token, reenterValue);
+
+ // Schedules a reentrancy from the token contract
+ await this.token.scheduleReenter(
+ reenterType.Before,
+ this.vault,
+ this.vault.interface.encodeFunctionData('deposit', [reenterValue, this.holder.address]),
+ );
+
+ // Initial share price
+ const sharesForDeposit = await this.vault.previewDeposit(value);
+ const sharesForReenter = await this.vault.previewDeposit(reenterValue);
+
+ await expect(this.vault.connect(this.holder).deposit(value, this.holder))
+ // Deposit normally, reentering before the internal `_update`
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.holder, value, sharesForDeposit)
+ // Reentrant deposit event → uses the same price
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.token, this.holder, reenterValue, sharesForReenter);
+
+ // Assert prices is kept
+ expect(await this.vault.previewDeposit(value)).to.equal(sharesForDeposit);
+ });
+
+ // During a `_withdraw`, the vault does `_burn(owner, shares)` -> `transfer(receiver, assets)`
+ // such that a reentrancy AFTER the transfer guarantees the price is kept the same.
+ // If the order of burn -> transfer is changed to transfer -> burn, the reentrancy could be triggered on an
+ // intermediate state in which the ratio of shares/assets has been decreased (more assets than shares).
+ it('correct share price is observed during reentrancy after withdraw', async function () {
+ // Deposit into the vault: holder gets `value` share, token.address gets `reenterValue` shares
+ await this.vault.connect(this.holder).deposit(value, this.holder);
+ await this.vault.connect(this.other).deposit(reenterValue, this.token);
+
+ // Schedules a reentrancy from the token contract
+ await this.token.scheduleReenter(
+ reenterType.After,
+ this.vault,
+ this.vault.interface.encodeFunctionData('withdraw', [reenterValue, this.holder.address, this.token.target]),
+ );
+
+ // Initial share price
+ const sharesForWithdraw = await this.vault.previewWithdraw(value);
+ const sharesForReenter = await this.vault.previewWithdraw(reenterValue);
+
+ // Do withdraw normally, triggering the _afterTokenTransfer hook
+ await expect(this.vault.connect(this.holder).withdraw(value, this.holder, this.holder))
+ // Main withdraw event
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.holder, this.holder, value, sharesForWithdraw)
+ // Reentrant withdraw event → uses the same price
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.token, this.holder, this.token, reenterValue, sharesForReenter);
+
+ // Assert price is kept
+ expect(await this.vault.previewWithdraw(value)).to.equal(sharesForWithdraw);
+ });
+
+ // Donate newly minted tokens to the vault during the reentracy causes the share price to increase.
+ // Still, the deposit that trigger the reentracy is not affected and get the previewed price.
+ // Further deposits will get a different price (getting fewer shares for the same value of assets)
+ it('share price change during reentracy does not affect deposit', async function () {
+ // Schedules a reentrancy from the token contract that mess up the share price
+ await this.token.scheduleReenter(
+ reenterType.Before,
+ this.token,
+ this.token.interface.encodeFunctionData('$_mint', [this.vault.target, reenterValue]),
+ );
+
+ // Price before
+ const sharesBefore = await this.vault.previewDeposit(value);
+
+ // Deposit, reentering before the internal `_update`
+ await expect(this.vault.connect(this.holder).deposit(value, this.holder))
+ // Price is as previewed
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.holder, value, sharesBefore);
+
+ // Price was modified during reentrancy
+ expect(await this.vault.previewDeposit(value)).to.lt(sharesBefore);
+ });
+
+ // Burn some tokens from the vault during the reentracy causes the share price to drop.
+ // Still, the withdraw that trigger the reentracy is not affected and get the previewed price.
+ // Further withdraw will get a different price (needing more shares for the same value of assets)
+ it('share price change during reentracy does not affect withdraw', async function () {
+ await this.vault.connect(this.holder).deposit(value, this.holder);
+ await this.vault.connect(this.other).deposit(value, this.other);
+
+ // Schedules a reentrancy from the token contract that mess up the share price
+ await this.token.scheduleReenter(
+ reenterType.After,
+ this.token,
+ this.token.interface.encodeFunctionData('$_burn', [this.vault.target, reenterValue]),
+ );
+
+ // Price before
+ const sharesBefore = await this.vault.previewWithdraw(value);
+
+ // Withdraw, triggering the _afterTokenTransfer hook
+ await expect(this.vault.connect(this.holder).withdraw(value, this.holder, this.holder))
+ // Price is as previewed
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.holder, this.holder, value, sharesBefore);
+
+ // Price was modified during reentrancy
+ expect(await this.vault.previewWithdraw(value)).to.gt(sharesBefore);
+ });
+ });
+
+ describe('limits', function () {
+ beforeEach(async function () {
+ const token = await ethers.deployContract('$ERC20DecimalsMock', [name, symbol, decimals]);
+ const vault = await ethers.deployContract('$ERC4626LimitsMock', ['', '', token]);
+
+ Object.assign(this, { token, vault });
+ });
+
+ it('reverts on deposit() above max deposit', async function () {
+ const maxDeposit = await this.vault.maxDeposit(this.holder);
+ await expect(this.vault.connect(this.holder).deposit(maxDeposit + 1n, this.recipient))
+ .to.be.revertedWithCustomError(this.vault, 'ERC4626ExceededMaxDeposit')
+ .withArgs(this.recipient, maxDeposit + 1n, maxDeposit);
+ });
+
+ it('reverts on mint() above max mint', async function () {
+ const maxMint = await this.vault.maxMint(this.holder);
+
+ await expect(this.vault.connect(this.holder).mint(maxMint + 1n, this.recipient))
+ .to.be.revertedWithCustomError(this.vault, 'ERC4626ExceededMaxMint')
+ .withArgs(this.recipient, maxMint + 1n, maxMint);
+ });
+
+ it('reverts on withdraw() above max withdraw', async function () {
+ const maxWithdraw = await this.vault.maxWithdraw(this.holder);
+
+ await expect(this.vault.connect(this.holder).withdraw(maxWithdraw + 1n, this.recipient, this.holder))
+ .to.be.revertedWithCustomError(this.vault, 'ERC4626ExceededMaxWithdraw')
+ .withArgs(this.holder, maxWithdraw + 1n, maxWithdraw);
+ });
+
+ it('reverts on redeem() above max redeem', async function () {
+ const maxRedeem = await this.vault.maxRedeem(this.holder);
+
+ await expect(this.vault.connect(this.holder).redeem(maxRedeem + 1n, this.recipient, this.holder))
+ .to.be.revertedWithCustomError(this.vault, 'ERC4626ExceededMaxRedeem')
+ .withArgs(this.holder, maxRedeem + 1n, maxRedeem);
+ });
+ });
+
+ for (const offset of [0n, 6n, 18n]) {
+ const parseToken = token => token * 10n ** decimals;
+ const parseShare = share => share * 10n ** (decimals + offset);
+
+ const virtualAssets = 1n;
+ const virtualShares = 10n ** offset;
+
+ describe(`offset: ${offset}`, function () {
+ beforeEach(async function () {
+ const token = await ethers.deployContract('$ERC20DecimalsMock', [name, symbol, decimals]);
+ const vault = await ethers.deployContract('$ERC4626OffsetMock', [name + ' Vault', symbol + 'V', token, offset]);
+
+ await token.$_mint(this.holder, ethers.MaxUint256 / 2n); // 50% of maximum
+ await token.$_approve(this.holder, vault, ethers.MaxUint256);
+ await vault.$_approve(this.holder, this.spender, ethers.MaxUint256);
+
+ Object.assign(this, { token, vault });
+ });
+
+ it('metadata', async function () {
+ expect(await this.vault.name()).to.equal(name + ' Vault');
+ expect(await this.vault.symbol()).to.equal(symbol + 'V');
+ expect(await this.vault.decimals()).to.equal(decimals + offset);
+ expect(await this.vault.asset()).to.equal(this.token);
+ });
+
+ describe('empty vault: no assets & no shares', function () {
+ it('status', async function () {
+ expect(await this.vault.totalAssets()).to.equal(0n);
+ });
+
+ it('deposit', async function () {
+ expect(await this.vault.maxDeposit(this.holder)).to.equal(ethers.MaxUint256);
+ expect(await this.vault.previewDeposit(parseToken(1n))).to.equal(parseShare(1n));
+
+ const tx = this.vault.connect(this.holder).deposit(parseToken(1n), this.recipient);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault],
+ [-parseToken(1n), parseToken(1n)],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.recipient, parseShare(1n));
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, parseToken(1n))
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, parseShare(1n))
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, parseToken(1n), parseShare(1n));
+ });
+
+ it('mint', async function () {
+ expect(await this.vault.maxMint(this.holder)).to.equal(ethers.MaxUint256);
+ expect(await this.vault.previewMint(parseShare(1n))).to.equal(parseToken(1n));
+
+ const tx = this.vault.connect(this.holder).mint(parseShare(1n), this.recipient);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault],
+ [-parseToken(1n), parseToken(1n)],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.recipient, parseShare(1n));
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, parseToken(1n))
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, parseShare(1n))
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, parseToken(1n), parseShare(1n));
+ });
+
+ it('withdraw', async function () {
+ expect(await this.vault.maxWithdraw(this.holder)).to.equal(0n);
+ expect(await this.vault.previewWithdraw(0n)).to.equal(0n);
+
+ const tx = this.vault.connect(this.holder).withdraw(0n, this.recipient, this.holder);
+
+ await expect(tx).to.changeTokenBalances(this.token, [this.vault, this.recipient], [0n, 0n]);
+ await expect(tx).to.changeTokenBalance(this.vault, this.holder, 0n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, 0n)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, 0n)
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, 0n, 0n);
+ });
+
+ it('redeem', async function () {
+ expect(await this.vault.maxRedeem(this.holder)).to.equal(0n);
+ expect(await this.vault.previewRedeem(0n)).to.equal(0n);
+
+ const tx = this.vault.connect(this.holder).redeem(0n, this.recipient, this.holder);
+
+ await expect(tx).to.changeTokenBalances(this.token, [this.vault, this.recipient], [0n, 0n]);
+ await expect(tx).to.changeTokenBalance(this.vault, this.holder, 0n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, 0n)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, 0n)
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, 0n, 0n);
+ });
+ });
+
+ describe('inflation attack: offset price by direct deposit of assets', function () {
+ beforeEach(async function () {
+ // Donate 1 token to the vault to offset the price
+ await this.token.$_mint(this.vault, parseToken(1n));
+ });
+
+ it('status', async function () {
+ expect(await this.vault.totalSupply()).to.equal(0n);
+ expect(await this.vault.totalAssets()).to.equal(parseToken(1n));
+ });
+
+ /**
+ * | offset | deposited assets | redeemable assets |
+ * |--------|----------------------|----------------------|
+ * | 0 | 1.000000000000000000 | 0. |
+ * | 6 | 1.000000000000000000 | 0.999999000000000000 |
+ * | 18 | 1.000000000000000000 | 0.999999999999999999 |
+ *
+ * Attack is possible, but made difficult by the offset. For the attack to be successful
+ * the attacker needs to frontrun a deposit 10**offset times bigger than what the victim
+ * was trying to deposit
+ */
+ it('deposit', async function () {
+ const effectiveAssets = (await this.vault.totalAssets()) + virtualAssets;
+ const effectiveShares = (await this.vault.totalSupply()) + virtualShares;
+
+ const depositAssets = parseToken(1n);
+ const expectedShares = (depositAssets * effectiveShares) / effectiveAssets;
+
+ expect(await this.vault.maxDeposit(this.holder)).to.equal(ethers.MaxUint256);
+ expect(await this.vault.previewDeposit(depositAssets)).to.equal(expectedShares);
+
+ const tx = this.vault.connect(this.holder).deposit(depositAssets, this.recipient);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault],
+ [-depositAssets, depositAssets],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.recipient, expectedShares);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, depositAssets)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, expectedShares)
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, depositAssets, expectedShares);
+ });
+
+ /**
+ * | offset | deposited assets | redeemable assets |
+ * |--------|----------------------|----------------------|
+ * | 0 | 1000000000000000001. | 1000000000000000001. |
+ * | 6 | 1000000000000000001. | 1000000000000000001. |
+ * | 18 | 1000000000000000001. | 1000000000000000001. |
+ *
+ * Using mint protects against inflation attack, but makes minting shares very expensive.
+ * The ER20 allowance for the underlying asset is needed to protect the user from (too)
+ * large deposits.
+ */
+ it('mint', async function () {
+ const effectiveAssets = (await this.vault.totalAssets()) + virtualAssets;
+ const effectiveShares = (await this.vault.totalSupply()) + virtualShares;
+
+ const mintShares = parseShare(1n);
+ const expectedAssets = (mintShares * effectiveAssets) / effectiveShares;
+
+ expect(await this.vault.maxMint(this.holder)).to.equal(ethers.MaxUint256);
+ expect(await this.vault.previewMint(mintShares)).to.equal(expectedAssets);
+
+ const tx = this.vault.connect(this.holder).mint(mintShares, this.recipient);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault],
+ [-expectedAssets, expectedAssets],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.recipient, mintShares);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, expectedAssets)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, mintShares)
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, expectedAssets, mintShares);
+ });
+
+ it('withdraw', async function () {
+ expect(await this.vault.maxWithdraw(this.holder)).to.equal(0n);
+ expect(await this.vault.previewWithdraw(0n)).to.equal(0n);
+
+ const tx = this.vault.connect(this.holder).withdraw(0n, this.recipient, this.holder);
+
+ await expect(tx).to.changeTokenBalances(this.token, [this.vault, this.recipient], [0n, 0n]);
+ await expect(tx).to.changeTokenBalance(this.vault, this.holder, 0n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, 0n)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, 0n)
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, 0n, 0n);
+ });
+
+ it('redeem', async function () {
+ expect(await this.vault.maxRedeem(this.holder)).to.equal(0n);
+ expect(await this.vault.previewRedeem(0n)).to.equal(0n);
+
+ const tx = this.vault.connect(this.holder).redeem(0n, this.recipient, this.holder);
+
+ await expect(tx).to.changeTokenBalances(this.token, [this.vault, this.recipient], [0n, 0n]);
+ await expect(tx).to.changeTokenBalance(this.vault, this.holder, 0n);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, 0n)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, 0n)
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, 0n, 0n);
+ });
+ });
+
+ describe('full vault: assets & shares', function () {
+ beforeEach(async function () {
+ // Add 1 token of underlying asset and 100 shares to the vault
+ await this.token.$_mint(this.vault, parseToken(1n));
+ await this.vault.$_mint(this.holder, parseShare(100n));
+ });
+
+ it('status', async function () {
+ expect(await this.vault.totalSupply()).to.equal(parseShare(100n));
+ expect(await this.vault.totalAssets()).to.equal(parseToken(1n));
+ });
+
+ /**
+ * | offset | deposited assets | redeemable assets |
+ * |--------|--------------------- |----------------------|
+ * | 0 | 1.000000000000000000 | 0.999999999999999999 |
+ * | 6 | 1.000000000000000000 | 0.999999999999999999 |
+ * | 18 | 1.000000000000000000 | 0.999999999999999999 |
+ *
+ * Virtual shares & assets captures part of the value
+ */
+ it('deposit', async function () {
+ const effectiveAssets = (await this.vault.totalAssets()) + virtualAssets;
+ const effectiveShares = (await this.vault.totalSupply()) + virtualShares;
+
+ const depositAssets = parseToken(1n);
+ const expectedShares = (depositAssets * effectiveShares) / effectiveAssets;
+
+ expect(await this.vault.maxDeposit(this.holder)).to.equal(ethers.MaxUint256);
+ expect(await this.vault.previewDeposit(depositAssets)).to.equal(expectedShares);
+
+ const tx = this.vault.connect(this.holder).deposit(depositAssets, this.recipient);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault],
+ [-depositAssets, depositAssets],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.recipient, expectedShares);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, depositAssets)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, expectedShares)
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, depositAssets, expectedShares);
+ });
+
+ /**
+ * | offset | deposited assets | redeemable assets |
+ * |--------|--------------------- |----------------------|
+ * | 0 | 0.010000000000000001 | 0.010000000000000000 |
+ * | 6 | 0.010000000000000001 | 0.010000000000000000 |
+ * | 18 | 0.010000000000000001 | 0.010000000000000000 |
+ *
+ * Virtual shares & assets captures part of the value
+ */
+ it('mint', async function () {
+ const effectiveAssets = (await this.vault.totalAssets()) + virtualAssets;
+ const effectiveShares = (await this.vault.totalSupply()) + virtualShares;
+
+ const mintShares = parseShare(1n);
+ const expectedAssets = (mintShares * effectiveAssets) / effectiveShares + 1n; // add for the rounding
+
+ expect(await this.vault.maxMint(this.holder)).to.equal(ethers.MaxUint256);
+ expect(await this.vault.previewMint(mintShares)).to.equal(expectedAssets);
+
+ const tx = this.vault.connect(this.holder).mint(mintShares, this.recipient);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault],
+ [-expectedAssets, expectedAssets],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.recipient, mintShares);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, expectedAssets)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, mintShares)
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, expectedAssets, mintShares);
+ });
+
+ it('withdraw', async function () {
+ const effectiveAssets = (await this.vault.totalAssets()) + virtualAssets;
+ const effectiveShares = (await this.vault.totalSupply()) + virtualShares;
+
+ const withdrawAssets = parseToken(1n);
+ const expectedShares = (withdrawAssets * effectiveShares) / effectiveAssets + 1n; // add for the rounding
+
+ expect(await this.vault.maxWithdraw(this.holder)).to.equal(withdrawAssets);
+ expect(await this.vault.previewWithdraw(withdrawAssets)).to.equal(expectedShares);
+
+ const tx = this.vault.connect(this.holder).withdraw(withdrawAssets, this.recipient, this.holder);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.vault, this.recipient],
+ [-withdrawAssets, withdrawAssets],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.holder, -expectedShares);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, withdrawAssets)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, expectedShares)
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, withdrawAssets, expectedShares);
+ });
+
+ it('withdraw with approval', async function () {
+ const assets = await this.vault.previewWithdraw(parseToken(1n));
+
+ await expect(this.vault.connect(this.other).withdraw(parseToken(1n), this.recipient, this.holder))
+ .to.be.revertedWithCustomError(this.vault, 'ERC20InsufficientAllowance')
+ .withArgs(this.other, 0n, assets);
+
+ await expect(this.vault.connect(this.spender).withdraw(parseToken(1n), this.recipient, this.holder)).to.not.be
+ .reverted;
+ });
+
+ it('redeem', async function () {
+ const effectiveAssets = (await this.vault.totalAssets()) + virtualAssets;
+ const effectiveShares = (await this.vault.totalSupply()) + virtualShares;
+
+ const redeemShares = parseShare(100n);
+ const expectedAssets = (redeemShares * effectiveAssets) / effectiveShares;
+
+ expect(await this.vault.maxRedeem(this.holder)).to.equal(redeemShares);
+ expect(await this.vault.previewRedeem(redeemShares)).to.equal(expectedAssets);
+
+ const tx = this.vault.connect(this.holder).redeem(redeemShares, this.recipient, this.holder);
+
+ await expect(tx).to.changeTokenBalances(
+ this.token,
+ [this.vault, this.recipient],
+ [-expectedAssets, expectedAssets],
+ );
+ await expect(tx).to.changeTokenBalance(this.vault, this.holder, -redeemShares);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, expectedAssets)
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, redeemShares)
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, expectedAssets, redeemShares);
+ });
+
+ it('redeem with approval', async function () {
+ await expect(this.vault.connect(this.other).redeem(parseShare(100n), this.recipient, this.holder))
+ .to.be.revertedWithCustomError(this.vault, 'ERC20InsufficientAllowance')
+ .withArgs(this.other, 0n, parseShare(100n));
+
+ await expect(this.vault.connect(this.spender).redeem(parseShare(100n), this.recipient, this.holder)).to.not.be
+ .reverted;
+ });
+ });
+ });
+ }
+
+ describe('ERC4626Fees', function () {
+ const feeBasisPoints = 500n; // 5%
+ const valueWithoutFees = 10_000n;
+ const fees = (valueWithoutFees * feeBasisPoints) / 10_000n;
+ const valueWithFees = valueWithoutFees + fees;
+
+ describe('input fees', function () {
+ beforeEach(async function () {
+ const token = await ethers.deployContract('$ERC20DecimalsMock', [name, symbol, 18n]);
+ const vault = await ethers.deployContract('$ERC4626FeesMock', [
+ '',
+ '',
+ token,
+ feeBasisPoints,
+ this.other,
+ 0n,
+ ethers.ZeroAddress,
+ ]);
+
+ await token.$_mint(this.holder, ethers.MaxUint256 / 2n);
+ await token.$_approve(this.holder, vault, ethers.MaxUint256 / 2n);
+
+ Object.assign(this, { token, vault });
+ });
+
+ it('deposit', async function () {
+ expect(await this.vault.previewDeposit(valueWithFees)).to.equal(valueWithoutFees);
+ this.tx = this.vault.connect(this.holder).deposit(valueWithFees, this.recipient);
+ });
+
+ it('mint', async function () {
+ expect(await this.vault.previewMint(valueWithoutFees)).to.equal(valueWithFees);
+ this.tx = this.vault.connect(this.holder).mint(valueWithoutFees, this.recipient);
+ });
+
+ afterEach(async function () {
+ await expect(this.tx).to.changeTokenBalances(
+ this.token,
+ [this.holder, this.vault, this.other],
+ [-valueWithFees, valueWithoutFees, fees],
+ );
+ await expect(this.tx).to.changeTokenBalance(this.vault, this.recipient, valueWithoutFees);
+ await expect(this.tx)
+ // get total
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.vault, valueWithFees)
+ // redirect fees
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.other, fees)
+ // mint shares
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.recipient, valueWithoutFees)
+ // deposit event
+ .to.emit(this.vault, 'Deposit')
+ .withArgs(this.holder, this.recipient, valueWithFees, valueWithoutFees);
+ });
+ });
+
+ describe('output fees', function () {
+ beforeEach(async function () {
+ const token = await ethers.deployContract('$ERC20DecimalsMock', [name, symbol, 18n]);
+ const vault = await ethers.deployContract('$ERC4626FeesMock', [
+ '',
+ '',
+ token,
+ 0n,
+ ethers.ZeroAddress,
+ feeBasisPoints,
+ this.other,
+ ]);
+
+ await token.$_mint(vault, ethers.MaxUint256 / 2n);
+ await vault.$_mint(this.holder, ethers.MaxUint256 / 2n);
+
+ Object.assign(this, { token, vault });
+ });
+
+ it('redeem', async function () {
+ expect(await this.vault.previewRedeem(valueWithFees)).to.equal(valueWithoutFees);
+ this.tx = this.vault.connect(this.holder).redeem(valueWithFees, this.recipient, this.holder);
+ });
+
+ it('withdraw', async function () {
+ expect(await this.vault.previewWithdraw(valueWithoutFees)).to.equal(valueWithFees);
+ this.tx = this.vault.connect(this.holder).withdraw(valueWithoutFees, this.recipient, this.holder);
+ });
+
+ afterEach(async function () {
+ await expect(this.tx).to.changeTokenBalances(
+ this.token,
+ [this.vault, this.recipient, this.other],
+ [-valueWithFees, valueWithoutFees, fees],
+ );
+ await expect(this.tx).to.changeTokenBalance(this.vault, this.holder, -valueWithFees);
+ await expect(this.tx)
+ // withdraw principal
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.recipient, valueWithoutFees)
+ // redirect fees
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.vault, this.other, fees)
+ // mint shares
+ .to.emit(this.vault, 'Transfer')
+ .withArgs(this.holder, ethers.ZeroAddress, valueWithFees)
+ // withdraw event
+ .to.emit(this.vault, 'Withdraw')
+ .withArgs(this.holder, this.recipient, this.holder, valueWithoutFees, valueWithFees);
+ });
+ });
+ });
+
+ /// Scenario inspired by solmate ERC4626 tests:
+ /// https://github.com/transmissions11/solmate/blob/main/src/test/ERC4626.t.sol
+ it('multiple mint, deposit, redeem & withdrawal', async function () {
+ // test designed with both asset using similar decimals
+ const [alice, bruce] = this.accounts;
+ const token = await ethers.deployContract('$ERC20DecimalsMock', [name, symbol, 18n]);
+ const vault = await ethers.deployContract('$ERC4626', ['', '', token]);
+
+ await token.$_mint(alice, 4000n);
+ await token.$_mint(bruce, 7001n);
+ await token.connect(alice).approve(vault, 4000n);
+ await token.connect(bruce).approve(vault, 7001n);
+
+ // 1. Alice mints 2000 shares (costs 2000 tokens)
+ await expect(vault.connect(alice).mint(2000n, alice))
+ .to.emit(token, 'Transfer')
+ .withArgs(alice, vault, 2000n)
+ .to.emit(vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, alice, 2000n);
+
+ expect(await vault.previewDeposit(2000n)).to.equal(2000n);
+ expect(await vault.balanceOf(alice)).to.equal(2000n);
+ expect(await vault.balanceOf(bruce)).to.equal(0n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(2000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(0n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(2000n);
+ expect(await vault.totalSupply()).to.equal(2000n);
+ expect(await vault.totalAssets()).to.equal(2000n);
+
+ // 2. Bruce deposits 4000 tokens (mints 4000 shares)
+ await expect(vault.connect(bruce).mint(4000n, bruce))
+ .to.emit(token, 'Transfer')
+ .withArgs(bruce, vault, 4000n)
+ .to.emit(vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, bruce, 4000n);
+
+ expect(await vault.previewDeposit(4000n)).to.equal(4000n);
+ expect(await vault.balanceOf(alice)).to.equal(2000n);
+ expect(await vault.balanceOf(bruce)).to.equal(4000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(2000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(4000n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(6000n);
+ expect(await vault.totalSupply()).to.equal(6000n);
+ expect(await vault.totalAssets()).to.equal(6000n);
+
+ // 3. Vault mutates by +3000 tokens (simulated yield returned from strategy)
+ await token.$_mint(vault, 3000n);
+
+ expect(await vault.balanceOf(alice)).to.equal(2000n);
+ expect(await vault.balanceOf(bruce)).to.equal(4000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(2999n); // used to be 3000, but virtual assets/shares captures part of the yield
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(5999n); // used to be 6000, but virtual assets/shares captures part of the yield
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(6000n);
+ expect(await vault.totalSupply()).to.equal(6000n);
+ expect(await vault.totalAssets()).to.equal(9000n);
+
+ // 4. Alice deposits 2000 tokens (mints 1333 shares)
+ await expect(vault.connect(alice).deposit(2000n, alice))
+ .to.emit(token, 'Transfer')
+ .withArgs(alice, vault, 2000n)
+ .to.emit(vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, alice, 1333n);
+
+ expect(await vault.balanceOf(alice)).to.equal(3333n);
+ expect(await vault.balanceOf(bruce)).to.equal(4000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(4999n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(6000n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(7333n);
+ expect(await vault.totalSupply()).to.equal(7333n);
+ expect(await vault.totalAssets()).to.equal(11000n);
+
+ // 5. Bruce mints 2000 shares (costs 3001 assets)
+ // NOTE: Bruce's assets spent got rounded towards infinity
+ // NOTE: Alices's vault assets got rounded towards infinity
+ await expect(vault.connect(bruce).mint(2000n, bruce))
+ .to.emit(token, 'Transfer')
+ .withArgs(bruce, vault, 3000n)
+ .to.emit(vault, 'Transfer')
+ .withArgs(ethers.ZeroAddress, bruce, 2000n);
+
+ expect(await vault.balanceOf(alice)).to.equal(3333n);
+ expect(await vault.balanceOf(bruce)).to.equal(6000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(4999n); // used to be 5000
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(9000n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(9333n);
+ expect(await vault.totalSupply()).to.equal(9333n);
+ expect(await vault.totalAssets()).to.equal(14000n); // used to be 14001
+
+ // 6. Vault mutates by +3000 tokens
+ // NOTE: Vault holds 17001 tokens, but sum of assetsOf() is 17000.
+ await token.$_mint(vault, 3000n);
+
+ expect(await vault.balanceOf(alice)).to.equal(3333n);
+ expect(await vault.balanceOf(bruce)).to.equal(6000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(6070n); // used to be 6071
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(10928n); // used to be 10929
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(9333n);
+ expect(await vault.totalSupply()).to.equal(9333n);
+ expect(await vault.totalAssets()).to.equal(17000n); // used to be 17001
+
+ // 7. Alice redeem 1333 shares (2428 assets)
+ await expect(vault.connect(alice).redeem(1333n, alice, alice))
+ .to.emit(vault, 'Transfer')
+ .withArgs(alice, ethers.ZeroAddress, 1333n)
+ .to.emit(token, 'Transfer')
+ .withArgs(vault, alice, 2427n); // used to be 2428
+
+ expect(await vault.balanceOf(alice)).to.equal(2000n);
+ expect(await vault.balanceOf(bruce)).to.equal(6000n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(3643n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(10929n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(8000n);
+ expect(await vault.totalSupply()).to.equal(8000n);
+ expect(await vault.totalAssets()).to.equal(14573n);
+
+ // 8. Bruce withdraws 2929 assets (1608 shares)
+ await expect(vault.connect(bruce).withdraw(2929n, bruce, bruce))
+ .to.emit(vault, 'Transfer')
+ .withArgs(bruce, ethers.ZeroAddress, 1608n)
+ .to.emit(token, 'Transfer')
+ .withArgs(vault, bruce, 2929n);
+
+ expect(await vault.balanceOf(alice)).to.equal(2000n);
+ expect(await vault.balanceOf(bruce)).to.equal(4392n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(3643n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(8000n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(6392n);
+ expect(await vault.totalSupply()).to.equal(6392n);
+ expect(await vault.totalAssets()).to.equal(11644n);
+
+ // 9. Alice withdraws 3643 assets (2000 shares)
+ // NOTE: Bruce's assets have been rounded back towards infinity
+ await expect(vault.connect(alice).withdraw(3643n, alice, alice))
+ .to.emit(vault, 'Transfer')
+ .withArgs(alice, ethers.ZeroAddress, 2000n)
+ .to.emit(token, 'Transfer')
+ .withArgs(vault, alice, 3643n);
+
+ expect(await vault.balanceOf(alice)).to.equal(0n);
+ expect(await vault.balanceOf(bruce)).to.equal(4392n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(0n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(8000n); // used to be 8001
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(4392n);
+ expect(await vault.totalSupply()).to.equal(4392n);
+ expect(await vault.totalAssets()).to.equal(8001n);
+
+ // 10. Bruce redeem 4392 shares (8001 tokens)
+ await expect(vault.connect(bruce).redeem(4392n, bruce, bruce))
+ .to.emit(vault, 'Transfer')
+ .withArgs(bruce, ethers.ZeroAddress, 4392n)
+ .to.emit(token, 'Transfer')
+ .withArgs(vault, bruce, 8000n); // used to be 8001
+
+ expect(await vault.balanceOf(alice)).to.equal(0n);
+ expect(await vault.balanceOf(bruce)).to.equal(0n);
+ expect(await vault.convertToAssets(await vault.balanceOf(alice))).to.equal(0n);
+ expect(await vault.convertToAssets(await vault.balanceOf(bruce))).to.equal(0n);
+ expect(await vault.convertToShares(await token.balanceOf(vault))).to.equal(0n);
+ expect(await vault.totalSupply()).to.equal(0n);
+ expect(await vault.totalAssets()).to.equal(1n); // used to be 0
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/draft-ERC20TemporaryApproval.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/draft-ERC20TemporaryApproval.test.js
new file mode 100644
index 000000000..a1f6362ad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/extensions/draft-ERC20TemporaryApproval.test.js
@@ -0,0 +1,142 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { max, min } = require('../../../helpers/math.js');
+
+const { shouldBehaveLikeERC20 } = require('../ERC20.behavior.js');
+
+const name = 'My Token';
+const symbol = 'MTKN';
+const initialSupply = 100n;
+
+async function fixture() {
+ // this.accounts is used by shouldBehaveLikeERC20
+ const accounts = await ethers.getSigners();
+ const [holder, recipient, other] = accounts;
+
+ const token = await ethers.deployContract('$ERC20TemporaryApproval', [name, symbol]);
+ await token.$_mint(holder, initialSupply);
+
+ const spender = await ethers.deployContract('$Address');
+ const batch = await ethers.deployContract('BatchCaller');
+ const getter = await ethers.deployContract('ERC20GetterHelper');
+
+ return { accounts, holder, recipient, other, token, spender, batch, getter };
+}
+
+describe('ERC20TemporaryApproval', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeERC20(initialSupply);
+
+ describe('setting and spending temporary allowance', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.holder).transfer(this.batch, initialSupply);
+ });
+
+ for (let {
+ description,
+ persistentAllowance,
+ temporaryAllowance,
+ amount,
+ temporaryExpected,
+ persistentExpected,
+ } of [
+ { description: 'can set temporary allowance', temporaryAllowance: 42n },
+ {
+ description: 'can set temporary allowance on top of persistent allowance',
+ temporaryAllowance: 42n,
+ persistentAllowance: 17n,
+ },
+ { description: 'support allowance overflow', temporaryAllowance: ethers.MaxUint256, persistentAllowance: 17n },
+ { description: 'consuming temporary allowance alone', temporaryAllowance: 42n, amount: 2n },
+ {
+ description: 'fallback to persistent allowance if temporary allowance is not sufficient',
+ temporaryAllowance: 42n,
+ persistentAllowance: 17n,
+ amount: 50n,
+ },
+ {
+ description: 'do not reduce infinite temporary allowance #1',
+ temporaryAllowance: ethers.MaxUint256,
+ amount: 50n,
+ temporaryExpected: ethers.MaxUint256,
+ },
+ {
+ description: 'do not reduce infinite temporary allowance #2',
+ temporaryAllowance: 17n,
+ persistentAllowance: ethers.MaxUint256,
+ amount: 50n,
+ temporaryExpected: ethers.MaxUint256,
+ persistentExpected: ethers.MaxUint256,
+ },
+ ]) {
+ persistentAllowance ??= 0n;
+ temporaryAllowance ??= 0n;
+ amount ??= 0n;
+ temporaryExpected ??= min(persistentAllowance + temporaryAllowance - amount, ethers.MaxUint256);
+ persistentExpected ??= persistentAllowance - max(amount - temporaryAllowance, 0n);
+
+ it(description, async function () {
+ await expect(
+ this.batch.execute(
+ [
+ persistentAllowance && {
+ target: this.token,
+ value: 0n,
+ data: this.token.interface.encodeFunctionData('approve', [this.spender.target, persistentAllowance]),
+ },
+ temporaryAllowance && {
+ target: this.token,
+ value: 0n,
+ data: this.token.interface.encodeFunctionData('temporaryApprove', [
+ this.spender.target,
+ temporaryAllowance,
+ ]),
+ },
+ amount && {
+ target: this.spender,
+ value: 0n,
+ data: this.spender.interface.encodeFunctionData('$functionCall', [
+ this.token.target,
+ this.token.interface.encodeFunctionData('transferFrom', [
+ this.batch.target,
+ this.recipient.address,
+ amount,
+ ]),
+ ]),
+ },
+ {
+ target: this.getter,
+ value: 0n,
+ data: this.getter.interface.encodeFunctionData('allowance', [
+ this.token.target,
+ this.batch.target,
+ this.spender.target,
+ ]),
+ },
+ ].filter(Boolean),
+ ),
+ )
+ .to.emit(this.getter, 'ERC20Allowance')
+ .withArgs(this.token, this.batch, this.spender, temporaryExpected);
+
+ expect(await this.token.allowance(this.batch, this.spender)).to.equal(persistentExpected);
+ });
+ }
+
+ it('reverts when the recipient is the zero address', async function () {
+ await expect(this.token.connect(this.holder).temporaryApprove(ethers.ZeroAddress, 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidSpender')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ it('reverts when the token owner is the zero address', async function () {
+ await expect(this.token.$_temporaryApprove(ethers.ZeroAddress, this.recipient, 1n))
+ .to.be.revertedWithCustomError(this.token, 'ERC20InvalidApprover')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/utils/SafeERC20.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/utils/SafeERC20.test.js
new file mode 100644
index 000000000..16b72bd6b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC20/utils/SafeERC20.test.js
@@ -0,0 +1,427 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'ERC20Mock';
+const symbol = 'ERC20Mock';
+const value = 100n;
+const data = '0x12345678';
+
+async function fixture() {
+ const [hasNoCode, owner, receiver, spender, other] = await ethers.getSigners();
+
+ const mock = await ethers.deployContract('$SafeERC20');
+ const erc20ReturnFalseMock = await ethers.deployContract('$ERC20ReturnFalseMock', [name, symbol]);
+ const erc20ReturnTrueMock = await ethers.deployContract('$ERC20', [name, symbol]); // default implementation returns true
+ const erc20NoReturnMock = await ethers.deployContract('$ERC20NoReturnMock', [name, symbol]);
+ const erc20ForceApproveMock = await ethers.deployContract('$ERC20ForceApproveMock', [name, symbol]);
+ const erc1363Mock = await ethers.deployContract('$ERC1363', [name, symbol]);
+ const erc1363ReturnFalseOnErc20Mock = await ethers.deployContract('$ERC1363ReturnFalseOnERC20Mock', [name, symbol]);
+ const erc1363ReturnFalseMock = await ethers.deployContract('$ERC1363ReturnFalseMock', [name, symbol]);
+ const erc1363NoReturnMock = await ethers.deployContract('$ERC1363NoReturnMock', [name, symbol]);
+ const erc1363ForceApproveMock = await ethers.deployContract('$ERC1363ForceApproveMock', [name, symbol]);
+ const erc1363Receiver = await ethers.deployContract('$ERC1363ReceiverMock');
+ const erc1363Spender = await ethers.deployContract('$ERC1363SpenderMock');
+
+ return {
+ hasNoCode,
+ owner,
+ receiver,
+ spender,
+ other,
+ mock,
+ erc20ReturnFalseMock,
+ erc20ReturnTrueMock,
+ erc20NoReturnMock,
+ erc20ForceApproveMock,
+ erc1363Mock,
+ erc1363ReturnFalseOnErc20Mock,
+ erc1363ReturnFalseMock,
+ erc1363NoReturnMock,
+ erc1363ForceApproveMock,
+ erc1363Receiver,
+ erc1363Spender,
+ };
+}
+
+describe('SafeERC20', function () {
+ before(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('with address that has no contract code', function () {
+ beforeEach(async function () {
+ this.token = this.hasNoCode;
+ });
+
+ it('reverts on transfer', async function () {
+ await expect(this.mock.$safeTransfer(this.token, this.receiver, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on transferFrom', async function () {
+ await expect(this.mock.$safeTransferFrom(this.token, this.mock, this.receiver, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on increaseAllowance', async function () {
+ // Call to 'token.allowance' does not return any data, resulting in a decoding error (revert without reason)
+ await expect(this.mock.$safeIncreaseAllowance(this.token, this.spender, 0n)).to.be.revertedWithoutReason();
+ });
+
+ it('reverts on decreaseAllowance', async function () {
+ // Call to 'token.allowance' does not return any data, resulting in a decoding error (revert without reason)
+ await expect(this.mock.$safeDecreaseAllowance(this.token, this.spender, 0n)).to.be.revertedWithoutReason();
+ });
+
+ it('reverts on forceApprove', async function () {
+ await expect(this.mock.$forceApprove(this.token, this.spender, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+ });
+
+ describe('with token that returns false on all calls', function () {
+ beforeEach(async function () {
+ this.token = this.erc20ReturnFalseMock;
+ });
+
+ it('reverts on transfer', async function () {
+ await expect(this.mock.$safeTransfer(this.token, this.receiver, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on transferFrom', async function () {
+ await expect(this.mock.$safeTransferFrom(this.token, this.mock, this.receiver, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on increaseAllowance', async function () {
+ await expect(this.mock.$safeIncreaseAllowance(this.token, this.spender, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on decreaseAllowance', async function () {
+ await expect(this.mock.$safeDecreaseAllowance(this.token, this.spender, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on forceApprove', async function () {
+ await expect(this.mock.$forceApprove(this.token, this.spender, 0n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+ });
+
+ describe('with token that returns true on all calls', function () {
+ beforeEach(async function () {
+ this.token = this.erc20ReturnTrueMock;
+ });
+
+ shouldOnlyRevertOnErrors();
+ });
+
+ describe('with token that returns no boolean values', function () {
+ beforeEach(async function () {
+ this.token = this.erc20NoReturnMock;
+ });
+
+ shouldOnlyRevertOnErrors();
+ });
+
+ describe('with usdt approval behaviour', function () {
+ beforeEach(async function () {
+ this.token = this.erc20ForceApproveMock;
+ });
+
+ describe('with initial approval', function () {
+ beforeEach(async function () {
+ await this.token.$_approve(this.mock, this.spender, 100n);
+ });
+
+ it('safeIncreaseAllowance works', async function () {
+ await this.mock.$safeIncreaseAllowance(this.token, this.spender, 10n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(110n);
+ });
+
+ it('safeDecreaseAllowance works', async function () {
+ await this.mock.$safeDecreaseAllowance(this.token, this.spender, 10n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(90n);
+ });
+
+ it('forceApprove works', async function () {
+ await this.mock.$forceApprove(this.token, this.spender, 200n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(200n);
+ });
+ });
+ });
+
+ describe('with standard ERC1363', function () {
+ beforeEach(async function () {
+ this.token = this.erc1363Mock;
+ });
+
+ shouldOnlyRevertOnErrors();
+
+ describe('transferAndCall', function () {
+ it('cannot transferAndCall to an EOA directly', async function () {
+ await this.token.$_mint(this.owner, 100n);
+
+ await expect(this.token.connect(this.owner).transferAndCall(this.receiver, value, ethers.Typed.bytes(data)))
+ .to.be.revertedWithCustomError(this.token, 'ERC1363InvalidReceiver')
+ .withArgs(this.receiver);
+ });
+
+ it('can transferAndCall to an EOA using helper', async function () {
+ await this.token.$_mint(this.mock, value);
+
+ await expect(this.mock.$transferAndCallRelaxed(this.token, this.receiver, value, data))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.mock, this.receiver, value);
+ });
+
+ it('can transferAndCall to an ERC1363Receiver using helper', async function () {
+ await this.token.$_mint(this.mock, value);
+
+ await expect(this.mock.$transferAndCallRelaxed(this.token, this.erc1363Receiver, value, data))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.mock, this.erc1363Receiver, value)
+ .to.emit(this.erc1363Receiver, 'Received')
+ .withArgs(this.mock, this.mock, value, data);
+ });
+ });
+
+ describe('transferFromAndCall', function () {
+ it('can transferFromAndCall to an EOA using helper', async function () {
+ await this.token.$_mint(this.owner, value);
+ await this.token.$_approve(this.owner, this.mock, ethers.MaxUint256);
+
+ await expect(this.mock.$transferFromAndCallRelaxed(this.token, this.owner, this.receiver, value, data))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, this.receiver, value);
+ });
+
+ it('can transferFromAndCall to an ERC1363Receiver using helper', async function () {
+ await this.token.$_mint(this.owner, value);
+ await this.token.$_approve(this.owner, this.mock, ethers.MaxUint256);
+
+ await expect(this.mock.$transferFromAndCallRelaxed(this.token, this.owner, this.erc1363Receiver, value, data))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, this.erc1363Receiver, value)
+ .to.emit(this.erc1363Receiver, 'Received')
+ .withArgs(this.mock, this.owner, value, data);
+ });
+ });
+
+ describe('approveAndCall', function () {
+ it('can approveAndCall to an EOA using helper', async function () {
+ await expect(this.mock.$approveAndCallRelaxed(this.token, this.receiver, value, data))
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.mock, this.receiver, value);
+ });
+
+ it('can approveAndCall to an ERC1363Spender using helper', async function () {
+ await expect(this.mock.$approveAndCallRelaxed(this.token, this.erc1363Spender, value, data))
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.mock, this.erc1363Spender, value)
+ .to.emit(this.erc1363Spender, 'Approved')
+ .withArgs(this.mock, value, data);
+ });
+ });
+ });
+
+ describe('with ERC1363 that returns false on all ERC20 calls', function () {
+ beforeEach(async function () {
+ this.token = this.erc1363ReturnFalseOnErc20Mock;
+ });
+
+ it('reverts on transferAndCallRelaxed', async function () {
+ await expect(this.mock.$transferAndCallRelaxed(this.token, this.erc1363Receiver, 0n, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1363TransferFailed')
+ .withArgs(this.erc1363Receiver, 0n);
+ });
+
+ it('reverts on transferFromAndCallRelaxed', async function () {
+ await expect(this.mock.$transferFromAndCallRelaxed(this.token, this.mock, this.erc1363Receiver, 0n, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1363TransferFromFailed')
+ .withArgs(this.mock, this.erc1363Receiver, 0n);
+ });
+
+ it('reverts on approveAndCallRelaxed', async function () {
+ await expect(this.mock.$approveAndCallRelaxed(this.token, this.erc1363Spender, 0n, data))
+ .to.be.revertedWithCustomError(this.token, 'ERC1363ApproveFailed')
+ .withArgs(this.erc1363Spender, 0n);
+ });
+ });
+
+ describe('with ERC1363 that returns false on all ERC1363 calls', function () {
+ beforeEach(async function () {
+ this.token = this.erc1363ReturnFalseMock;
+ });
+
+ it('reverts on transferAndCallRelaxed', async function () {
+ await expect(this.mock.$transferAndCallRelaxed(this.token, this.erc1363Receiver, 0n, data))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on transferFromAndCallRelaxed', async function () {
+ await expect(this.mock.$transferFromAndCallRelaxed(this.token, this.mock, this.erc1363Receiver, 0n, data))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+
+ it('reverts on approveAndCallRelaxed', async function () {
+ await expect(this.mock.$approveAndCallRelaxed(this.token, this.erc1363Spender, 0n, data))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedOperation')
+ .withArgs(this.token);
+ });
+ });
+
+ describe('with ERC1363 that returns no boolean values', function () {
+ beforeEach(async function () {
+ this.token = this.erc1363NoReturnMock;
+ });
+
+ it('reverts on transferAndCallRelaxed', async function () {
+ await expect(
+ this.mock.$transferAndCallRelaxed(this.token, this.erc1363Receiver, 0n, data),
+ ).to.be.revertedWithoutReason();
+ });
+
+ it('reverts on transferFromAndCallRelaxed', async function () {
+ await expect(
+ this.mock.$transferFromAndCallRelaxed(this.token, this.mock, this.erc1363Receiver, 0n, data),
+ ).to.be.revertedWithoutReason();
+ });
+
+ it('reverts on approveAndCallRelaxed', async function () {
+ await expect(
+ this.mock.$approveAndCallRelaxed(this.token, this.erc1363Spender, 0n, data),
+ ).to.be.revertedWithoutReason();
+ });
+ });
+
+ describe('with ERC1363 with usdt approval behaviour', function () {
+ beforeEach(async function () {
+ this.token = this.erc1363ForceApproveMock;
+ });
+
+ describe('without initial approval', function () {
+ it('approveAndCallRelaxed works when recipient is an EOA', async function () {
+ await this.mock.$approveAndCallRelaxed(this.token, this.spender, 10n, data);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(10n);
+ });
+
+ it('approveAndCallRelaxed works when recipient is a contract', async function () {
+ await this.mock.$approveAndCallRelaxed(this.token, this.erc1363Spender, 10n, data);
+ expect(await this.token.allowance(this.mock, this.erc1363Spender)).to.equal(10n);
+ });
+ });
+
+ describe('with initial approval', function () {
+ it('approveAndCallRelaxed works when recipient is an EOA', async function () {
+ await this.token.$_approve(this.mock, this.spender, 100n);
+
+ await this.mock.$approveAndCallRelaxed(this.token, this.spender, 10n, data);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(10n);
+ });
+
+ it('approveAndCallRelaxed reverts when recipient is a contract', async function () {
+ await this.token.$_approve(this.mock, this.erc1363Spender, 100n);
+ await expect(this.mock.$approveAndCallRelaxed(this.token, this.erc1363Spender, 10n, data)).to.be.revertedWith(
+ 'USDT approval failure',
+ );
+ });
+ });
+ });
+});
+
+function shouldOnlyRevertOnErrors() {
+ describe('transfers', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, 100n);
+ await this.token.$_mint(this.mock, 100n);
+ await this.token.$_approve(this.owner, this.mock, ethers.MaxUint256);
+ });
+
+ it("doesn't revert on transfer", async function () {
+ await expect(this.mock.$safeTransfer(this.token, this.receiver, 10n))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.mock, this.receiver, 10n);
+ });
+
+ it("doesn't revert on transferFrom", async function () {
+ await expect(this.mock.$safeTransferFrom(this.token, this.owner, this.receiver, 10n))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, this.receiver, 10n);
+ });
+ });
+
+ describe('approvals', function () {
+ describe('with zero allowance', function () {
+ beforeEach(async function () {
+ await this.token.$_approve(this.mock, this.spender, 0n);
+ });
+
+ it("doesn't revert when force approving a non-zero allowance", async function () {
+ await this.mock.$forceApprove(this.token, this.spender, 100n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(100n);
+ });
+
+ it("doesn't revert when force approving a zero allowance", async function () {
+ await this.mock.$forceApprove(this.token, this.spender, 0n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(0n);
+ });
+
+ it("doesn't revert when increasing the allowance", async function () {
+ await this.mock.$safeIncreaseAllowance(this.token, this.spender, 10n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(10n);
+ });
+
+ it('reverts when decreasing the allowance', async function () {
+ await expect(this.mock.$safeDecreaseAllowance(this.token, this.spender, 10n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedDecreaseAllowance')
+ .withArgs(this.spender, 0n, 10n);
+ });
+ });
+
+ describe('with non-zero allowance', function () {
+ beforeEach(async function () {
+ await this.token.$_approve(this.mock, this.spender, 100n);
+ });
+
+ it("doesn't revert when force approving a non-zero allowance", async function () {
+ await this.mock.$forceApprove(this.token, this.spender, 20n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(20n);
+ });
+
+ it("doesn't revert when force approving a zero allowance", async function () {
+ await this.mock.$forceApprove(this.token, this.spender, 0n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(0n);
+ });
+
+ it("doesn't revert when increasing the allowance", async function () {
+ await this.mock.$safeIncreaseAllowance(this.token, this.spender, 10n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(110n);
+ });
+
+ it("doesn't revert when decreasing the allowance to a positive value", async function () {
+ await this.mock.$safeDecreaseAllowance(this.token, this.spender, 50n);
+ expect(await this.token.allowance(this.mock, this.spender)).to.equal(50n);
+ });
+
+ it('reverts when decreasing the allowance to a negative value', async function () {
+ await expect(this.mock.$safeDecreaseAllowance(this.token, this.spender, 200n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeERC20FailedDecreaseAllowance')
+ .withArgs(this.spender, 100n, 200n);
+ });
+ });
+ });
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721.behavior.js
new file mode 100644
index 000000000..b9dd80d6d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721.behavior.js
@@ -0,0 +1,972 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+const { anyValue } = require('@nomicfoundation/hardhat-chai-matchers/withArgs');
+
+const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior');
+const { RevertType } = require('../../helpers/enums');
+
+const firstTokenId = 5042n;
+const secondTokenId = 79217n;
+const nonExistentTokenId = 13n;
+const fourthTokenId = 4n;
+const baseURI = 'https://api.example.com/v1/';
+
+const RECEIVER_MAGIC_VALUE = '0x150b7a02';
+
+function shouldBehaveLikeERC721() {
+ beforeEach(async function () {
+ const [owner, newOwner, approved, operator, other] = this.accounts;
+ Object.assign(this, { owner, newOwner, approved, operator, other });
+ });
+
+ shouldSupportInterfaces(['ERC721']);
+
+ describe('with minted tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, firstTokenId);
+ await this.token.$_mint(this.owner, secondTokenId);
+ this.to = this.other;
+ });
+
+ describe('balanceOf', function () {
+ describe('when the given address owns some tokens', function () {
+ it('returns the amount of tokens owned by the given address', async function () {
+ expect(await this.token.balanceOf(this.owner)).to.equal(2n);
+ });
+ });
+
+ describe('when the given address does not own any tokens', function () {
+ it('returns 0', async function () {
+ expect(await this.token.balanceOf(this.other)).to.equal(0n);
+ });
+ });
+
+ describe('when querying the zero address', function () {
+ it('throws', async function () {
+ await expect(this.token.balanceOf(ethers.ZeroAddress))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidOwner')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+ });
+
+ describe('ownerOf', function () {
+ describe('when the given token ID was tracked by this token', function () {
+ const tokenId = firstTokenId;
+
+ it('returns the owner of the given token ID', async function () {
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.owner);
+ });
+ });
+
+ describe('when the given token ID was not tracked by this token', function () {
+ const tokenId = nonExistentTokenId;
+
+ it('reverts', async function () {
+ await expect(this.token.ownerOf(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+ });
+ });
+ });
+
+ describe('transfers', function () {
+ const tokenId = firstTokenId;
+ const data = '0x42';
+
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.approved, tokenId);
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, true);
+ });
+
+ const transferWasSuccessful = () => {
+ it('transfers the ownership of the given token ID to the given address', async function () {
+ await this.tx();
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.to);
+ });
+
+ it('emits a Transfer event', async function () {
+ await expect(this.tx()).to.emit(this.token, 'Transfer').withArgs(this.owner, this.to, tokenId);
+ });
+
+ it('clears the approval for the token ID with no event', async function () {
+ await expect(this.tx()).to.not.emit(this.token, 'Approval');
+
+ expect(await this.token.getApproved(tokenId)).to.equal(ethers.ZeroAddress);
+ });
+
+ it('adjusts owners balances', async function () {
+ const balanceBefore = await this.token.balanceOf(this.owner);
+ await this.tx();
+ expect(await this.token.balanceOf(this.owner)).to.equal(balanceBefore - 1n);
+ });
+
+ it('adjusts owners tokens by index', async function () {
+ if (!this.token.tokenOfOwnerByIndex) return;
+
+ await this.tx();
+ expect(await this.token.tokenOfOwnerByIndex(this.to, 0n)).to.equal(tokenId);
+ expect(await this.token.tokenOfOwnerByIndex(this.owner, 0n)).to.not.equal(tokenId);
+ });
+ };
+
+ const shouldTransferTokensByUsers = function (fragment, opts = {}) {
+ describe('when called by the owner', function () {
+ beforeEach(async function () {
+ this.tx = () =>
+ this.token.connect(this.owner)[fragment](this.owner, this.to, tokenId, ...(opts.extra ?? []));
+ });
+ transferWasSuccessful();
+ });
+
+ describe('when called by the approved individual', function () {
+ beforeEach(async function () {
+ this.tx = () =>
+ this.token.connect(this.approved)[fragment](this.owner, this.to, tokenId, ...(opts.extra ?? []));
+ });
+ transferWasSuccessful();
+ });
+
+ describe('when called by the operator', function () {
+ beforeEach(async function () {
+ this.tx = () =>
+ this.token.connect(this.operator)[fragment](this.owner, this.to, tokenId, ...(opts.extra ?? []));
+ });
+ transferWasSuccessful();
+ });
+
+ describe('when called by the owner without an approved user', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(ethers.ZeroAddress, tokenId);
+ this.tx = () =>
+ this.token.connect(this.operator)[fragment](this.owner, this.to, tokenId, ...(opts.extra ?? []));
+ });
+ transferWasSuccessful();
+ });
+
+ describe('when sent to the owner', function () {
+ beforeEach(async function () {
+ this.tx = () =>
+ this.token.connect(this.owner)[fragment](this.owner, this.owner, tokenId, ...(opts.extra ?? []));
+ });
+
+ it('keeps ownership of the token', async function () {
+ await this.tx();
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.owner);
+ });
+
+ it('clears the approval for the token ID', async function () {
+ await this.tx();
+ expect(await this.token.getApproved(tokenId)).to.equal(ethers.ZeroAddress);
+ });
+
+ it('emits only a transfer event', async function () {
+ await expect(this.tx()).to.emit(this.token, 'Transfer').withArgs(this.owner, this.owner, tokenId);
+ });
+
+ it('keeps the owner balance', async function () {
+ const balanceBefore = await this.token.balanceOf(this.owner);
+ await this.tx();
+ expect(await this.token.balanceOf(this.owner)).to.equal(balanceBefore);
+ });
+
+ it('keeps same tokens by index', async function () {
+ if (!this.token.tokenOfOwnerByIndex) return;
+
+ expect(await Promise.all([0n, 1n].map(i => this.token.tokenOfOwnerByIndex(this.owner, i)))).to.have.members(
+ [firstTokenId, secondTokenId],
+ );
+ });
+ });
+
+ describe('when the address of the previous owner is incorrect', function () {
+ it('reverts', async function () {
+ await expect(
+ this.token.connect(this.owner)[fragment](this.other, this.other, tokenId, ...(opts.extra ?? [])),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721IncorrectOwner')
+ .withArgs(this.other, tokenId, this.owner);
+ });
+ });
+
+ describe('when the sender is not authorized for the token id', function () {
+ if (opts.unrestricted) {
+ it('does not revert', async function () {
+ await this.token.connect(this.other)[fragment](this.owner, this.other, tokenId, ...(opts.extra ?? []));
+ });
+ } else {
+ it('reverts', async function () {
+ await expect(
+ this.token.connect(this.other)[fragment](this.owner, this.other, tokenId, ...(opts.extra ?? [])),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721InsufficientApproval')
+ .withArgs(this.other, tokenId);
+ });
+ }
+ });
+
+ describe('when the given token ID does not exist', function () {
+ it('reverts', async function () {
+ await expect(
+ this.token
+ .connect(this.owner)
+ [fragment](this.owner, this.other, nonExistentTokenId, ...(opts.extra ?? [])),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+ });
+
+ describe('when the address to transfer the token to is the zero address', function () {
+ it('reverts', async function () {
+ await expect(
+ this.token.connect(this.owner)[fragment](this.owner, ethers.ZeroAddress, tokenId, ...(opts.extra ?? [])),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+ };
+
+ const shouldTransferSafely = function (fragment, data, opts = {}) {
+ // sanity
+ it('function exists', async function () {
+ expect(this.token.interface.hasFunction(fragment)).to.be.true;
+ });
+
+ describe('to a user account', function () {
+ shouldTransferTokensByUsers(fragment, opts);
+ });
+
+ describe('to a valid receiver contract', function () {
+ beforeEach(async function () {
+ this.to = await ethers.deployContract('ERC721ReceiverMock', [RECEIVER_MAGIC_VALUE, RevertType.None]);
+ });
+
+ shouldTransferTokensByUsers(fragment, opts);
+
+ it('calls onERC721Received', async function () {
+ await expect(this.token.connect(this.owner)[fragment](this.owner, this.to, tokenId, ...(opts.extra ?? [])))
+ .to.emit(this.to, 'Received')
+ .withArgs(this.owner, this.owner, tokenId, data, anyValue);
+ });
+
+ it('calls onERC721Received from approved', async function () {
+ await expect(
+ this.token.connect(this.approved)[fragment](this.owner, this.to, tokenId, ...(opts.extra ?? [])),
+ )
+ .to.emit(this.to, 'Received')
+ .withArgs(this.approved, this.owner, tokenId, data, anyValue);
+ });
+
+ describe('with an invalid token id', function () {
+ it('reverts', async function () {
+ await expect(
+ this.token
+ .connect(this.approved)
+ [fragment](this.owner, this.to, nonExistentTokenId, ...(opts.extra ?? [])),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+ });
+ });
+ };
+
+ for (const { fnName, opts } of [
+ { fnName: 'transferFrom', opts: {} },
+ { fnName: '$_transfer', opts: { unrestricted: true } },
+ ]) {
+ describe(`via ${fnName}`, function () {
+ shouldTransferTokensByUsers(fnName, opts);
+ });
+ }
+
+ for (const { fnName, opts } of [
+ { fnName: 'safeTransferFrom', opts: {} },
+ { fnName: '$_safeTransfer', opts: { unrestricted: true } },
+ ]) {
+ describe(`via ${fnName}`, function () {
+ describe('with data', function () {
+ shouldTransferSafely(fnName, data, { ...opts, extra: [ethers.Typed.bytes(data)] });
+ });
+
+ describe('without data', function () {
+ shouldTransferSafely(fnName, '0x', opts);
+ });
+
+ describe('to a receiver contract returning unexpected value', function () {
+ it('reverts', async function () {
+ const invalidReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ '0xdeadbeef',
+ RevertType.None,
+ ]);
+
+ await expect(this.token.connect(this.owner)[fnName](this.owner, invalidReceiver, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(invalidReceiver);
+ });
+ });
+
+ describe('to a receiver contract that reverts with message', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.RevertWithMessage,
+ ]);
+
+ await expect(
+ this.token.connect(this.owner)[fnName](this.owner, revertingReceiver, tokenId),
+ ).to.be.revertedWith('ERC721ReceiverMock: reverting');
+ });
+ });
+
+ describe('to a receiver contract that reverts without message', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.RevertWithoutMessage,
+ ]);
+
+ await expect(this.token.connect(this.owner)[fnName](this.owner, revertingReceiver, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(revertingReceiver);
+ });
+ });
+
+ describe('to a receiver contract that reverts with custom error', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.RevertWithCustomError,
+ ]);
+
+ await expect(this.token.connect(this.owner)[fnName](this.owner, revertingReceiver, tokenId))
+ .to.be.revertedWithCustomError(revertingReceiver, 'CustomError')
+ .withArgs(RECEIVER_MAGIC_VALUE);
+ });
+ });
+
+ describe('to a receiver contract that panics', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.Panic,
+ ]);
+
+ await expect(
+ this.token.connect(this.owner)[fnName](this.owner, revertingReceiver, tokenId),
+ ).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+ });
+
+ describe('to a contract that does not implement the required function', function () {
+ it('reverts', async function () {
+ const nonReceiver = await ethers.deployContract('CallReceiverMock');
+
+ await expect(this.token.connect(this.owner)[fnName](this.owner, nonReceiver, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(nonReceiver);
+ });
+ });
+ });
+ }
+ });
+
+ describe('safe mint', function () {
+ const tokenId = fourthTokenId;
+ const data = '0x42';
+
+ describe('via safeMint', function () {
+ // regular minting is tested in ERC721Mintable.test.js and others
+ it('calls onERC721Received — with data', async function () {
+ const receiver = await ethers.deployContract('ERC721ReceiverMock', [RECEIVER_MAGIC_VALUE, RevertType.None]);
+
+ await expect(await this.token.$_safeMint(receiver, tokenId, ethers.Typed.bytes(data)))
+ .to.emit(receiver, 'Received')
+ .withArgs(anyValue, ethers.ZeroAddress, tokenId, data, anyValue);
+ });
+
+ it('calls onERC721Received — without data', async function () {
+ const receiver = await ethers.deployContract('ERC721ReceiverMock', [RECEIVER_MAGIC_VALUE, RevertType.None]);
+
+ await expect(await this.token.$_safeMint(receiver, tokenId))
+ .to.emit(receiver, 'Received')
+ .withArgs(anyValue, ethers.ZeroAddress, tokenId, '0x', anyValue);
+ });
+
+ describe('to a receiver contract returning unexpected value', function () {
+ it('reverts', async function () {
+ const invalidReceiver = await ethers.deployContract('ERC721ReceiverMock', ['0xdeadbeef', RevertType.None]);
+
+ await expect(this.token.$_safeMint(invalidReceiver, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(invalidReceiver);
+ });
+ });
+
+ describe('to a receiver contract that reverts with message', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.RevertWithMessage,
+ ]);
+
+ await expect(this.token.$_safeMint(revertingReceiver, tokenId)).to.be.revertedWith(
+ 'ERC721ReceiverMock: reverting',
+ );
+ });
+ });
+
+ describe('to a receiver contract that reverts without message', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.RevertWithoutMessage,
+ ]);
+
+ await expect(this.token.$_safeMint(revertingReceiver, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(revertingReceiver);
+ });
+ });
+
+ describe('to a receiver contract that reverts with custom error', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.RevertWithCustomError,
+ ]);
+
+ await expect(this.token.$_safeMint(revertingReceiver, tokenId))
+ .to.be.revertedWithCustomError(revertingReceiver, 'CustomError')
+ .withArgs(RECEIVER_MAGIC_VALUE);
+ });
+ });
+
+ describe('to a receiver contract that panics', function () {
+ it('reverts', async function () {
+ const revertingReceiver = await ethers.deployContract('ERC721ReceiverMock', [
+ RECEIVER_MAGIC_VALUE,
+ RevertType.Panic,
+ ]);
+
+ await expect(this.token.$_safeMint(revertingReceiver, tokenId)).to.be.revertedWithPanic(
+ PANIC_CODES.DIVISION_BY_ZERO,
+ );
+ });
+ });
+
+ describe('to a contract that does not implement the required function', function () {
+ it('reverts', async function () {
+ const nonReceiver = await ethers.deployContract('CallReceiverMock');
+
+ await expect(this.token.$_safeMint(nonReceiver, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(nonReceiver);
+ });
+ });
+ });
+ });
+
+ describe('approve', function () {
+ const tokenId = firstTokenId;
+
+ const itClearsApproval = function () {
+ it('clears approval for the token', async function () {
+ expect(await this.token.getApproved(tokenId)).to.equal(ethers.ZeroAddress);
+ });
+ };
+
+ const itApproves = function () {
+ it('sets the approval for the target address', async function () {
+ expect(await this.token.getApproved(tokenId)).to.equal(this.approved ?? this.approved);
+ });
+ };
+
+ const itEmitsApprovalEvent = function () {
+ it('emits an approval event', async function () {
+ await expect(this.tx)
+ .to.emit(this.token, 'Approval')
+ .withArgs(this.owner, this.approved ?? this.approved, tokenId);
+ });
+ };
+
+ describe('when clearing approval', function () {
+ describe('when there was no prior approval', function () {
+ beforeEach(async function () {
+ this.approved = ethers.ZeroAddress;
+ this.tx = await this.token.connect(this.owner).approve(this.approved, tokenId);
+ });
+
+ itClearsApproval();
+ itEmitsApprovalEvent();
+ });
+
+ describe('when there was a prior approval', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.other, tokenId);
+ this.approved = ethers.ZeroAddress;
+ this.tx = await this.token.connect(this.owner).approve(this.approved, tokenId);
+ });
+
+ itClearsApproval();
+ itEmitsApprovalEvent();
+ });
+ });
+
+ describe('when approving a non-zero address', function () {
+ describe('when there was no prior approval', function () {
+ beforeEach(async function () {
+ this.tx = await this.token.connect(this.owner).approve(this.approved, tokenId);
+ });
+
+ itApproves();
+ itEmitsApprovalEvent();
+ });
+
+ describe('when there was a prior approval to the same address', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.approved, tokenId);
+ this.tx = await this.token.connect(this.owner).approve(this.approved, tokenId);
+ });
+
+ itApproves();
+ itEmitsApprovalEvent();
+ });
+
+ describe('when there was a prior approval to a different address', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.other, tokenId);
+ this.tx = await this.token.connect(this.owner).approve(this.approved, tokenId);
+ });
+
+ itApproves();
+ itEmitsApprovalEvent();
+ });
+ });
+
+ describe('when the sender does not own the given token ID', function () {
+ it('reverts', async function () {
+ await expect(this.token.connect(this.other).approve(this.approved, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidApprover')
+ .withArgs(this.other);
+ });
+ });
+
+ describe('when the sender is approved for the given token ID', function () {
+ it('reverts', async function () {
+ await this.token.connect(this.owner).approve(this.approved, tokenId);
+
+ await expect(this.token.connect(this.approved).approve(this.other, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidApprover')
+ .withArgs(this.approved);
+ });
+ });
+
+ describe('when the sender is an operator', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, true);
+
+ this.tx = await this.token.connect(this.operator).approve(this.approved, tokenId);
+ });
+
+ itApproves();
+ itEmitsApprovalEvent();
+ });
+
+ describe('when the given token ID does not exist', function () {
+ it('reverts', async function () {
+ await expect(this.token.connect(this.operator).approve(this.approved, nonExistentTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+ });
+ });
+
+ describe('setApprovalForAll', function () {
+ describe('when the operator willing to approve is not the owner', function () {
+ describe('when there is no operator approval set by the sender', function () {
+ it('approves the operator', async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, true);
+
+ expect(await this.token.isApprovedForAll(this.owner, this.operator)).to.be.true;
+ });
+
+ it('emits an approval event', async function () {
+ await expect(this.token.connect(this.owner).setApprovalForAll(this.operator, true))
+ .to.emit(this.token, 'ApprovalForAll')
+ .withArgs(this.owner, this.operator, true);
+ });
+ });
+
+ describe('when the operator was set as not approved', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, false);
+ });
+
+ it('approves the operator', async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, true);
+
+ expect(await this.token.isApprovedForAll(this.owner, this.operator)).to.be.true;
+ });
+
+ it('emits an approval event', async function () {
+ await expect(this.token.connect(this.owner).setApprovalForAll(this.operator, true))
+ .to.emit(this.token, 'ApprovalForAll')
+ .withArgs(this.owner, this.operator, true);
+ });
+
+ it('can unset the operator approval', async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, false);
+
+ expect(await this.token.isApprovedForAll(this.owner, this.operator)).to.be.false;
+ });
+ });
+
+ describe('when the operator was already approved', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, true);
+ });
+
+ it('keeps the approval to the given address', async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.operator, true);
+
+ expect(await this.token.isApprovedForAll(this.owner, this.operator)).to.be.true;
+ });
+
+ it('emits an approval event', async function () {
+ await expect(this.token.connect(this.owner).setApprovalForAll(this.operator, true))
+ .to.emit(this.token, 'ApprovalForAll')
+ .withArgs(this.owner, this.operator, true);
+ });
+ });
+ });
+
+ describe('when the operator is address zero', function () {
+ it('reverts', async function () {
+ await expect(this.token.connect(this.owner).setApprovalForAll(ethers.ZeroAddress, true))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidOperator')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+ });
+
+ describe('getApproved', function () {
+ describe('when token is not minted', function () {
+ it('reverts', async function () {
+ await expect(this.token.getApproved(nonExistentTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+ });
+
+ describe('when token has been minted ', function () {
+ it('should return the zero address', async function () {
+ expect(await this.token.getApproved(firstTokenId)).to.equal(ethers.ZeroAddress);
+ });
+
+ describe('when account has been approved', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.approved, firstTokenId);
+ });
+
+ it('returns approved account', async function () {
+ expect(await this.token.getApproved(firstTokenId)).to.equal(this.approved);
+ });
+ });
+ });
+ });
+ });
+
+ describe('_mint(address, uint256)', function () {
+ it('reverts with a null destination address', async function () {
+ await expect(this.token.$_mint(ethers.ZeroAddress, firstTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ describe('with minted token', function () {
+ beforeEach(async function () {
+ this.tx = await this.token.$_mint(this.owner, firstTokenId);
+ });
+
+ it('emits a Transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(ethers.ZeroAddress, this.owner, firstTokenId);
+ });
+
+ it('creates the token', async function () {
+ expect(await this.token.balanceOf(this.owner)).to.equal(1n);
+ expect(await this.token.ownerOf(firstTokenId)).to.equal(this.owner);
+ });
+
+ it('reverts when adding a token id that already exists', async function () {
+ await expect(this.token.$_mint(this.owner, firstTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+ });
+
+ describe('_burn', function () {
+ it('reverts when burning a non-existent token id', async function () {
+ await expect(this.token.$_burn(nonExistentTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+
+ describe('with minted tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, firstTokenId);
+ await this.token.$_mint(this.owner, secondTokenId);
+ });
+
+ describe('with burnt token', function () {
+ beforeEach(async function () {
+ this.tx = await this.token.$_burn(firstTokenId);
+ });
+
+ it('emits a Transfer event', async function () {
+ await expect(this.tx).to.emit(this.token, 'Transfer').withArgs(this.owner, ethers.ZeroAddress, firstTokenId);
+ });
+
+ it('deletes the token', async function () {
+ expect(await this.token.balanceOf(this.owner)).to.equal(1n);
+ await expect(this.token.ownerOf(firstTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(firstTokenId);
+ });
+
+ it('reverts when burning a token id that has been deleted', async function () {
+ await expect(this.token.$_burn(firstTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(firstTokenId);
+ });
+ });
+ });
+ });
+}
+
+function shouldBehaveLikeERC721Enumerable() {
+ beforeEach(async function () {
+ const [owner, newOwner, approved, operator, other] = this.accounts;
+ Object.assign(this, { owner, newOwner, approved, operator, other });
+ });
+
+ shouldSupportInterfaces(['ERC721Enumerable']);
+
+ describe('with minted tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, firstTokenId);
+ await this.token.$_mint(this.owner, secondTokenId);
+ this.to = this.other;
+ });
+
+ describe('totalSupply', function () {
+ it('returns total token supply', async function () {
+ expect(await this.token.totalSupply()).to.equal(2n);
+ });
+ });
+
+ describe('tokenOfOwnerByIndex', function () {
+ describe('when the given index is lower than the amount of tokens owned by the given address', function () {
+ it('returns the token ID placed at the given index', async function () {
+ expect(await this.token.tokenOfOwnerByIndex(this.owner, 0n)).to.equal(firstTokenId);
+ });
+ });
+
+ describe('when the index is greater than or equal to the total tokens owned by the given address', function () {
+ it('reverts', async function () {
+ await expect(this.token.tokenOfOwnerByIndex(this.owner, 2n))
+ .to.be.revertedWithCustomError(this.token, 'ERC721OutOfBoundsIndex')
+ .withArgs(this.owner, 2n);
+ });
+ });
+
+ describe('when the given address does not own any token', function () {
+ it('reverts', async function () {
+ await expect(this.token.tokenOfOwnerByIndex(this.other, 0n))
+ .to.be.revertedWithCustomError(this.token, 'ERC721OutOfBoundsIndex')
+ .withArgs(this.other, 0n);
+ });
+ });
+
+ describe('after transferring all tokens to another user', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).transferFrom(this.owner, this.other, firstTokenId);
+ await this.token.connect(this.owner).transferFrom(this.owner, this.other, secondTokenId);
+ });
+
+ it('returns correct token IDs for target', async function () {
+ expect(await this.token.balanceOf(this.other)).to.equal(2n);
+
+ expect(await Promise.all([0n, 1n].map(i => this.token.tokenOfOwnerByIndex(this.other, i)))).to.have.members([
+ firstTokenId,
+ secondTokenId,
+ ]);
+ });
+
+ it('returns empty collection for original owner', async function () {
+ expect(await this.token.balanceOf(this.owner)).to.equal(0n);
+ await expect(this.token.tokenOfOwnerByIndex(this.owner, 0n))
+ .to.be.revertedWithCustomError(this.token, 'ERC721OutOfBoundsIndex')
+ .withArgs(this.owner, 0n);
+ });
+ });
+ });
+
+ describe('tokenByIndex', function () {
+ it('returns all tokens', async function () {
+ expect(await Promise.all([0n, 1n].map(i => this.token.tokenByIndex(i)))).to.have.members([
+ firstTokenId,
+ secondTokenId,
+ ]);
+ });
+
+ it('reverts if index is greater than supply', async function () {
+ await expect(this.token.tokenByIndex(2n))
+ .to.be.revertedWithCustomError(this.token, 'ERC721OutOfBoundsIndex')
+ .withArgs(ethers.ZeroAddress, 2n);
+ });
+
+ for (const tokenId of [firstTokenId, secondTokenId]) {
+ it(`returns all tokens after burning token ${tokenId} and minting new tokens`, async function () {
+ const newTokenId = 300n;
+ const anotherNewTokenId = 400n;
+
+ await this.token.$_burn(tokenId);
+ await this.token.$_mint(this.newOwner, newTokenId);
+ await this.token.$_mint(this.newOwner, anotherNewTokenId);
+
+ expect(await this.token.totalSupply()).to.equal(3n);
+
+ expect(await Promise.all([0n, 1n, 2n].map(i => this.token.tokenByIndex(i))))
+ .to.have.members([firstTokenId, secondTokenId, newTokenId, anotherNewTokenId].filter(x => x !== tokenId))
+ .to.not.include(tokenId);
+ });
+ }
+ });
+ });
+
+ describe('_mint(address, uint256)', function () {
+ it('reverts with a null destination address', async function () {
+ await expect(this.token.$_mint(ethers.ZeroAddress, firstTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+
+ describe('with minted token', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, firstTokenId);
+ });
+
+ it('adjusts owner tokens by index', async function () {
+ expect(await this.token.tokenOfOwnerByIndex(this.owner, 0n)).to.equal(firstTokenId);
+ });
+
+ it('adjusts all tokens list', async function () {
+ expect(await this.token.tokenByIndex(0n)).to.equal(firstTokenId);
+ });
+ });
+ });
+
+ describe('_burn', function () {
+ it('reverts when burning a non-existent token id', async function () {
+ await expect(this.token.$_burn(firstTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(firstTokenId);
+ });
+
+ describe('with minted tokens', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, firstTokenId);
+ await this.token.$_mint(this.owner, secondTokenId);
+ });
+
+ describe('with burnt token', function () {
+ beforeEach(async function () {
+ await this.token.$_burn(firstTokenId);
+ });
+
+ it('removes that token from the token list of the owner', async function () {
+ expect(await this.token.tokenOfOwnerByIndex(this.owner, 0n)).to.equal(secondTokenId);
+ });
+
+ it('adjusts all tokens list', async function () {
+ expect(await this.token.tokenByIndex(0n)).to.equal(secondTokenId);
+ });
+
+ it('burns all tokens', async function () {
+ await this.token.$_burn(secondTokenId);
+ expect(await this.token.totalSupply()).to.equal(0n);
+
+ await expect(this.token.tokenByIndex(0n))
+ .to.be.revertedWithCustomError(this.token, 'ERC721OutOfBoundsIndex')
+ .withArgs(ethers.ZeroAddress, 0n);
+ });
+ });
+ });
+ });
+}
+
+function shouldBehaveLikeERC721Metadata(name, symbol) {
+ shouldSupportInterfaces(['ERC721Metadata']);
+
+ describe('metadata', function () {
+ it('has a name', async function () {
+ expect(await this.token.name()).to.equal(name);
+ });
+
+ it('has a symbol', async function () {
+ expect(await this.token.symbol()).to.equal(symbol);
+ });
+
+ describe('token URI', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, firstTokenId);
+ });
+
+ it('return empty string by default', async function () {
+ expect(await this.token.tokenURI(firstTokenId)).to.equal('');
+ });
+
+ it('reverts when queried for non existent token id', async function () {
+ await expect(this.token.tokenURI(nonExistentTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+
+ describe('base URI', function () {
+ beforeEach(function () {
+ if (!this.token.interface.hasFunction('setBaseURI')) {
+ this.skip();
+ }
+ });
+
+ it('base URI can be set', async function () {
+ await this.token.setBaseURI(baseURI);
+ expect(await this.token.baseURI()).to.equal(baseURI);
+ });
+
+ it('base URI is added as a prefix to the token URI', async function () {
+ await this.token.setBaseURI(baseURI);
+ expect(await this.token.tokenURI(firstTokenId)).to.equal(baseURI + firstTokenId.toString());
+ });
+
+ it('token URI can be changed by changing the base URI', async function () {
+ await this.token.setBaseURI(baseURI);
+ const newBaseURI = 'https://api.example.com/v2/';
+ await this.token.setBaseURI(newBaseURI);
+ expect(await this.token.tokenURI(firstTokenId)).to.equal(newBaseURI + firstTokenId.toString());
+ });
+ });
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeERC721,
+ shouldBehaveLikeERC721Enumerable,
+ shouldBehaveLikeERC721Metadata,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721.test.js
new file mode 100644
index 000000000..1454cb057
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721.test.js
@@ -0,0 +1,23 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldBehaveLikeERC721, shouldBehaveLikeERC721Metadata } = require('./ERC721.behavior');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+
+async function fixture() {
+ return {
+ accounts: await ethers.getSigners(),
+ token: await ethers.deployContract('$ERC721', [name, symbol]),
+ };
+}
+
+describe('ERC721', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeERC721();
+ shouldBehaveLikeERC721Metadata(name, symbol);
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721Enumerable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721Enumerable.test.js
new file mode 100644
index 000000000..a3bdea73f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/ERC721Enumerable.test.js
@@ -0,0 +1,28 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const {
+ shouldBehaveLikeERC721,
+ shouldBehaveLikeERC721Metadata,
+ shouldBehaveLikeERC721Enumerable,
+} = require('./ERC721.behavior');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+
+async function fixture() {
+ return {
+ accounts: await ethers.getSigners(),
+ token: await ethers.deployContract('$ERC721Enumerable', [name, symbol]),
+ };
+}
+
+describe('ERC721', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeERC721();
+ shouldBehaveLikeERC721Metadata(name, symbol);
+ shouldBehaveLikeERC721Enumerable();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Burnable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Burnable.test.js
new file mode 100644
index 000000000..d6f0b80c4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Burnable.test.js
@@ -0,0 +1,77 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+const tokenId = 1n;
+const otherTokenId = 2n;
+const unknownTokenId = 3n;
+
+async function fixture() {
+ const [owner, approved, another] = await ethers.getSigners();
+ const token = await ethers.deployContract('$ERC721Burnable', [name, symbol]);
+ return { owner, approved, another, token };
+}
+
+describe('ERC721Burnable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('like a burnable ERC721', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, tokenId);
+ await this.token.$_mint(this.owner, otherTokenId);
+ });
+
+ describe('burn', function () {
+ describe('when successful', function () {
+ it('emits a burn event, burns the given token ID and adjusts the balance of the owner', async function () {
+ const balanceBefore = await this.token.balanceOf(this.owner);
+
+ await expect(this.token.connect(this.owner).burn(tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId);
+
+ await expect(this.token.ownerOf(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+
+ expect(await this.token.balanceOf(this.owner)).to.equal(balanceBefore - 1n);
+ });
+ });
+
+ describe('when there is a previous approval burned', function () {
+ beforeEach(async function () {
+ await this.token.connect(this.owner).approve(this.approved, tokenId);
+ await this.token.connect(this.owner).burn(tokenId);
+ });
+
+ describe('getApproved', function () {
+ it('reverts', async function () {
+ await expect(this.token.getApproved(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+ });
+ });
+ });
+
+ describe('when there is no previous approval burned', function () {
+ it('reverts', async function () {
+ await expect(this.token.connect(this.another).burn(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InsufficientApproval')
+ .withArgs(this.another, tokenId);
+ });
+ });
+
+ describe('when the given token ID was not tracked by this contract', function () {
+ it('reverts', async function () {
+ await expect(this.token.connect(this.owner).burn(unknownTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(unknownTokenId);
+ });
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.t.sol
new file mode 100644
index 000000000..eca15e717
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.t.sol
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+// solhint-disable func-name-mixedcase
+
+import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
+import {ERC721Consecutive} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Consecutive.sol";
+import {Test, StdUtils} from "forge-std/Test.sol";
+
+function toSingleton(address account) pure returns (address[] memory) {
+ address[] memory accounts = new address[](1);
+ accounts[0] = account;
+ return accounts;
+}
+
+contract ERC721ConsecutiveTarget is StdUtils, ERC721Consecutive {
+ uint96 private immutable _offset;
+ uint256 public totalMinted = 0;
+
+ constructor(address[] memory receivers, uint256[] memory batches, uint256 startingId) ERC721("", "") {
+ _offset = uint96(startingId);
+ for (uint256 i = 0; i < batches.length; i++) {
+ address receiver = receivers[i % receivers.length];
+ uint96 batchSize = uint96(bound(batches[i], 0, _maxBatchSize()));
+ _mintConsecutive(receiver, batchSize);
+ totalMinted += batchSize;
+ }
+ }
+
+ function burn(uint256 tokenId) public {
+ _burn(tokenId);
+ }
+
+ function _firstConsecutiveId() internal view virtual override returns (uint96) {
+ return _offset;
+ }
+}
+
+contract ERC721ConsecutiveTest is Test {
+ function test_balance(address receiver, uint256[] calldata batches, uint96 startingId) public {
+ vm.assume(receiver != address(0));
+
+ uint256 startingTokenId = bound(startingId, 0, 5000);
+
+ ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingTokenId);
+
+ assertEq(token.balanceOf(receiver), token.totalMinted());
+ }
+
+ function test_ownership(
+ address receiver,
+ uint256[] calldata batches,
+ uint256[2] calldata unboundedTokenId,
+ uint96 startingId
+ ) public {
+ vm.assume(receiver != address(0));
+
+ uint256 startingTokenId = bound(startingId, 0, 5000);
+
+ ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingTokenId);
+
+ if (token.totalMinted() > 0) {
+ uint256 validTokenId = bound(
+ unboundedTokenId[0],
+ startingTokenId,
+ startingTokenId + token.totalMinted() - 1
+ );
+ assertEq(token.ownerOf(validTokenId), receiver);
+ }
+
+ uint256 invalidTokenId = bound(
+ unboundedTokenId[1],
+ startingTokenId + token.totalMinted(),
+ startingTokenId + token.totalMinted() + 1
+ );
+ vm.expectRevert();
+ token.ownerOf(invalidTokenId);
+ }
+
+ function test_burn(
+ address receiver,
+ uint256[] calldata batches,
+ uint256 unboundedTokenId,
+ uint96 startingId
+ ) public {
+ vm.assume(receiver != address(0));
+
+ uint256 startingTokenId = bound(startingId, 0, 5000);
+
+ ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingTokenId);
+
+ // only test if we minted at least one token
+ uint256 supply = token.totalMinted();
+ vm.assume(supply > 0);
+
+ // burn a token in [0; supply[
+ uint256 tokenId = bound(unboundedTokenId, startingTokenId, startingTokenId + supply - 1);
+ token.burn(tokenId);
+
+ // balance should have decreased
+ assertEq(token.balanceOf(receiver), supply - 1);
+
+ // token should be burnt
+ vm.expectRevert();
+ token.ownerOf(tokenId);
+ }
+
+ function test_transfer(
+ address[2] calldata accounts,
+ uint256[2] calldata unboundedBatches,
+ uint256[2] calldata unboundedTokenId,
+ uint96 startingId
+ ) public {
+ vm.assume(accounts[0] != address(0));
+ vm.assume(accounts[1] != address(0));
+ vm.assume(accounts[0] != accounts[1]);
+
+ uint256 startingTokenId = bound(startingId, 1, 5000);
+
+ address[] memory receivers = new address[](2);
+ receivers[0] = accounts[0];
+ receivers[1] = accounts[1];
+
+ // We assume _maxBatchSize is 5000 (the default). This test will break otherwise.
+ uint256[] memory batches = new uint256[](2);
+ batches[0] = bound(unboundedBatches[0], startingTokenId, 5000);
+ batches[1] = bound(unboundedBatches[1], startingTokenId, 5000);
+
+ ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(receivers, batches, startingTokenId);
+
+ uint256 tokenId0 = bound(unboundedTokenId[0], startingTokenId, batches[0]);
+ uint256 tokenId1 = bound(unboundedTokenId[1], startingTokenId, batches[1]) + batches[0];
+
+ assertEq(token.ownerOf(tokenId0), accounts[0]);
+ assertEq(token.ownerOf(tokenId1), accounts[1]);
+ assertEq(token.balanceOf(accounts[0]), batches[0]);
+ assertEq(token.balanceOf(accounts[1]), batches[1]);
+
+ vm.prank(accounts[0]);
+ token.transferFrom(accounts[0], accounts[1], tokenId0);
+
+ assertEq(token.ownerOf(tokenId0), accounts[1]);
+ assertEq(token.ownerOf(tokenId1), accounts[1]);
+ assertEq(token.balanceOf(accounts[0]), batches[0] - 1);
+ assertEq(token.balanceOf(accounts[1]), batches[1] + 1);
+
+ vm.prank(accounts[1]);
+ token.transferFrom(accounts[1], accounts[0], tokenId1);
+
+ assertEq(token.ownerOf(tokenId0), accounts[1]);
+ assertEq(token.ownerOf(tokenId1), accounts[0]);
+ assertEq(token.balanceOf(accounts[0]), batches[0]);
+ assertEq(token.balanceOf(accounts[1]), batches[1]);
+ }
+
+ function test_start_consecutive_id(
+ address receiver,
+ uint256[2] calldata unboundedBatches,
+ uint256[2] calldata unboundedTokenId,
+ uint96 startingId
+ ) public {
+ vm.assume(receiver != address(0));
+
+ uint256 startingTokenId = bound(startingId, 1, 5000);
+
+ // We assume _maxBatchSize is 5000 (the default). This test will break otherwise.
+ uint256[] memory batches = new uint256[](2);
+ batches[0] = bound(unboundedBatches[0], startingTokenId, 5000);
+ batches[1] = bound(unboundedBatches[1], startingTokenId, 5000);
+
+ ERC721ConsecutiveTarget token = new ERC721ConsecutiveTarget(toSingleton(receiver), batches, startingTokenId);
+
+ uint256 tokenId0 = bound(unboundedTokenId[0], startingTokenId, batches[0]);
+ uint256 tokenId1 = bound(unboundedTokenId[1], startingTokenId, batches[1]);
+
+ assertEq(token.ownerOf(tokenId0), receiver);
+ assertEq(token.ownerOf(tokenId1), receiver);
+ assertEq(token.balanceOf(receiver), batches[0] + batches[1]);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.test.js
new file mode 100644
index 000000000..f62d6dc5b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Consecutive.test.js
@@ -0,0 +1,236 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { sum } = require('../../../helpers/math');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+
+describe('ERC721Consecutive', function () {
+ for (const offset of [0n, 1n, 42n]) {
+ describe(`with offset ${offset}`, function () {
+ async function fixture() {
+ const accounts = await ethers.getSigners();
+ const [alice, bruce, chris, receiver] = accounts;
+
+ const batches = [
+ { receiver: alice, amount: 0n },
+ { receiver: alice, amount: 1n },
+ { receiver: alice, amount: 2n },
+ { receiver: bruce, amount: 5n },
+ { receiver: chris, amount: 0n },
+ { receiver: alice, amount: 7n },
+ ];
+ const delegates = [alice, chris];
+
+ const token = await ethers.deployContract('$ERC721ConsecutiveMock', [
+ name,
+ symbol,
+ offset,
+ delegates,
+ batches.map(({ receiver }) => receiver),
+ batches.map(({ amount }) => amount),
+ ]);
+
+ return { accounts, alice, bruce, chris, receiver, batches, delegates, token };
+ }
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('minting during construction', function () {
+ it('events are emitted at construction', async function () {
+ let first = offset;
+ for (const batch of this.batches) {
+ if (batch.amount > 0) {
+ await expect(this.token.deploymentTransaction())
+ .to.emit(this.token, 'ConsecutiveTransfer')
+ .withArgs(
+ first /* fromTokenId */,
+ first + batch.amount - 1n /* toTokenId */,
+ ethers.ZeroAddress /* fromAddress */,
+ batch.receiver /* toAddress */,
+ );
+ } else {
+ // ".to.not.emit" only looks at event name, and doesn't check the parameters
+ }
+ first += batch.amount;
+ }
+ });
+
+ it('ownership is set', async function () {
+ const owners = [
+ ...Array(Number(offset)).fill(ethers.ZeroAddress),
+ ...this.batches.flatMap(({ receiver, amount }) => Array(Number(amount)).fill(receiver.address)),
+ ];
+
+ for (const tokenId in owners) {
+ if (owners[tokenId] != ethers.ZeroAddress) {
+ expect(await this.token.ownerOf(tokenId)).to.equal(owners[tokenId]);
+ }
+ }
+ });
+
+ it('balance & voting power are set', async function () {
+ for (const account of this.accounts) {
+ const balance =
+ sum(...this.batches.filter(({ receiver }) => receiver === account).map(({ amount }) => amount)) ?? 0n;
+
+ expect(await this.token.balanceOf(account)).to.equal(balance);
+
+ // If not delegated at construction, check before + do delegation
+ if (!this.delegates.includes(account)) {
+ expect(await this.token.getVotes(account)).to.equal(0n);
+
+ await this.token.connect(account).delegate(account);
+ }
+
+ // At this point all accounts should have delegated
+ expect(await this.token.getVotes(account)).to.equal(balance);
+ }
+ });
+
+ it('reverts on consecutive minting to the zero address', async function () {
+ await expect(
+ ethers.deployContract('$ERC721ConsecutiveMock', [
+ name,
+ symbol,
+ offset,
+ this.delegates,
+ [ethers.ZeroAddress],
+ [10],
+ ]),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidReceiver')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('minting after construction', function () {
+ it('consecutive minting is not possible after construction', async function () {
+ await expect(this.token.$_mintConsecutive(this.alice, 10)).to.be.revertedWithCustomError(
+ this.token,
+ 'ERC721ForbiddenBatchMint',
+ );
+ });
+
+ it('simple minting is possible after construction', async function () {
+ const tokenId = sum(...this.batches.map(b => b.amount)) + offset;
+
+ await expect(this.token.ownerOf(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+
+ await expect(this.token.$_mint(this.alice, tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.alice, tokenId);
+ });
+
+ it('cannot mint a token that has been batched minted', async function () {
+ const tokenId = sum(...this.batches.map(b => b.amount)) + offset - 1n;
+
+ expect(await this.token.ownerOf(tokenId)).to.not.equal(ethers.ZeroAddress);
+
+ await expect(this.token.$_mint(this.alice, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InvalidSender')
+ .withArgs(ethers.ZeroAddress);
+ });
+ });
+
+ describe('ERC721 behavior', function () {
+ const tokenId = offset + 1n;
+
+ it('core takes over ownership on transfer', async function () {
+ await this.token.connect(this.alice).transferFrom(this.alice, this.receiver, tokenId);
+
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.receiver);
+ });
+
+ it('tokens can be burned and re-minted #1', async function () {
+ await expect(this.token.connect(this.alice).$_burn(tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.alice, ethers.ZeroAddress, tokenId);
+
+ await expect(this.token.ownerOf(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+
+ await expect(this.token.$_mint(this.bruce, tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.bruce, tokenId);
+
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.bruce);
+ });
+
+ it('tokens can be burned and re-minted #2', async function () {
+ const tokenId = sum(...this.batches.map(({ amount }) => amount)) + offset;
+
+ await expect(this.token.ownerOf(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+
+ // mint
+ await expect(this.token.$_mint(this.alice, tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.alice, tokenId);
+
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.alice);
+
+ // burn
+ await expect(await this.token.$_burn(tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.alice, ethers.ZeroAddress, tokenId);
+
+ await expect(this.token.ownerOf(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+
+ // re-mint
+ await expect(this.token.$_mint(this.bruce, tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.bruce, tokenId);
+
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.bruce);
+ });
+ });
+ });
+ }
+
+ describe('invalid use', function () {
+ const receiver = ethers.Wallet.createRandom();
+
+ it('cannot mint a batch larger than 5000', async function () {
+ const factory = await ethers.getContractFactory('$ERC721ConsecutiveMock');
+
+ await expect(ethers.deployContract('$ERC721ConsecutiveMock', [name, symbol, 0, [], [receiver], [5001n]]))
+ .to.be.revertedWithCustomError(factory, 'ERC721ExceededMaxBatchMint')
+ .withArgs(5001n, 5000n);
+ });
+
+ it('cannot use single minting during construction', async function () {
+ const factory = await ethers.getContractFactory('$ERC721ConsecutiveNoConstructorMintMock');
+
+ await expect(
+ ethers.deployContract('$ERC721ConsecutiveNoConstructorMintMock', [name, symbol]),
+ ).to.be.revertedWithCustomError(factory, 'ERC721ForbiddenMint');
+ });
+
+ it('cannot use single minting during construction', async function () {
+ const factory = await ethers.getContractFactory('$ERC721ConsecutiveNoConstructorMintMock');
+
+ await expect(
+ ethers.deployContract('$ERC721ConsecutiveNoConstructorMintMock', [name, symbol]),
+ ).to.be.revertedWithCustomError(factory, 'ERC721ForbiddenMint');
+ });
+
+ it('consecutive mint not compatible with enumerability', async function () {
+ const factory = await ethers.getContractFactory('$ERC721ConsecutiveEnumerableMock');
+
+ await expect(
+ ethers.deployContract('$ERC721ConsecutiveEnumerableMock', [name, symbol, [receiver], [100n]]),
+ ).to.be.revertedWithCustomError(factory, 'ERC721EnumerableForbiddenBatchMint');
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Pausable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Pausable.test.js
new file mode 100644
index 000000000..acf731a45
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Pausable.test.js
@@ -0,0 +1,81 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+const tokenId = 1n;
+const otherTokenId = 2n;
+const data = ethers.Typed.bytes('0x42');
+
+async function fixture() {
+ const [owner, receiver, operator] = await ethers.getSigners();
+ const token = await ethers.deployContract('$ERC721Pausable', [name, symbol]);
+ return { owner, receiver, operator, token };
+}
+
+describe('ERC721Pausable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('when token is paused', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, tokenId);
+ await this.token.$_pause();
+ });
+
+ it('reverts when trying to transferFrom', async function () {
+ await expect(
+ this.token.connect(this.owner).transferFrom(this.owner, this.receiver, tokenId),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to safeTransferFrom', async function () {
+ await expect(
+ this.token.connect(this.owner).safeTransferFrom(this.owner, this.receiver, tokenId),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to safeTransferFrom with data', async function () {
+ await expect(
+ this.token.connect(this.owner).safeTransferFrom(this.owner, this.receiver, tokenId, data),
+ ).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ it('reverts when trying to mint', async function () {
+ await expect(this.token.$_mint(this.receiver, otherTokenId)).to.be.revertedWithCustomError(
+ this.token,
+ 'EnforcedPause',
+ );
+ });
+
+ it('reverts when trying to burn', async function () {
+ await expect(this.token.$_burn(tokenId)).to.be.revertedWithCustomError(this.token, 'EnforcedPause');
+ });
+
+ describe('getApproved', function () {
+ it('returns approved address', async function () {
+ expect(await this.token.getApproved(tokenId)).to.equal(ethers.ZeroAddress);
+ });
+ });
+
+ describe('balanceOf', function () {
+ it('returns the amount of tokens owned by the given address', async function () {
+ expect(await this.token.balanceOf(this.owner)).to.equal(1n);
+ });
+ });
+
+ describe('ownerOf', function () {
+ it('returns the amount of tokens owned by the given address', async function () {
+ expect(await this.token.ownerOf(tokenId)).to.equal(this.owner);
+ });
+ });
+
+ describe('isApprovedForAll', function () {
+ it('returns the approval of the operator', async function () {
+ expect(await this.token.isApprovedForAll(this.owner, this.operator)).to.be.false;
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Royalty.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Royalty.test.js
new file mode 100644
index 000000000..e11954ae7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Royalty.test.js
@@ -0,0 +1,57 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldBehaveLikeERC2981 } = require('../../common/ERC2981.behavior');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+
+const tokenId1 = 1n;
+const tokenId2 = 2n;
+const royalty = 200n;
+const salePrice = 1000n;
+
+async function fixture() {
+ const [account1, account2, recipient] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC721Royalty', [name, symbol]);
+ await token.$_mint(account1, tokenId1);
+ await token.$_mint(account1, tokenId2);
+
+ return { account1, account2, recipient, token };
+}
+
+describe('ERC721Royalty', function () {
+ beforeEach(async function () {
+ Object.assign(
+ this,
+ await loadFixture(fixture),
+ { tokenId1, tokenId2, royalty, salePrice }, // set for behavior tests
+ );
+ });
+
+ describe('token specific functions', function () {
+ beforeEach(async function () {
+ await this.token.$_setTokenRoyalty(tokenId1, this.recipient, royalty);
+ });
+
+ it('royalty information are kept during burn and re-mint', async function () {
+ await this.token.$_burn(tokenId1);
+
+ expect(await this.token.royaltyInfo(tokenId1, salePrice)).to.deep.equal([
+ this.recipient.address,
+ (salePrice * royalty) / 10000n,
+ ]);
+
+ await this.token.$_mint(this.account2, tokenId1);
+
+ expect(await this.token.royaltyInfo(tokenId1, salePrice)).to.deep.equal([
+ this.recipient.address,
+ (salePrice * royalty) / 10000n,
+ ]);
+ });
+ });
+
+ shouldBehaveLikeERC2981();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721URIStorage.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721URIStorage.test.js
new file mode 100644
index 000000000..830c13a73
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721URIStorage.test.js
@@ -0,0 +1,121 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldSupportInterfaces } = require('../../../utils/introspection/SupportsInterface.behavior');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+const baseURI = 'https://api.example.com/v1/';
+const otherBaseURI = 'https://api.example.com/v2/';
+const sampleUri = 'mock://mytoken';
+const tokenId = 1n;
+const nonExistentTokenId = 2n;
+
+async function fixture() {
+ const [owner] = await ethers.getSigners();
+ const token = await ethers.deployContract('$ERC721URIStorageMock', [name, symbol]);
+ return { owner, token };
+}
+
+describe('ERC721URIStorage', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldSupportInterfaces(['0x49064906']);
+
+ describe('token URI', function () {
+ beforeEach(async function () {
+ await this.token.$_mint(this.owner, tokenId);
+ });
+
+ it('it is empty by default', async function () {
+ expect(await this.token.tokenURI(tokenId)).to.equal('');
+ });
+
+ it('reverts when queried for non existent token id', async function () {
+ await expect(this.token.tokenURI(nonExistentTokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(nonExistentTokenId);
+ });
+
+ it('can be set for a token id', async function () {
+ await this.token.$_setTokenURI(tokenId, sampleUri);
+ expect(await this.token.tokenURI(tokenId)).to.equal(sampleUri);
+ });
+
+ it('setting the uri emits an event', async function () {
+ await expect(this.token.$_setTokenURI(tokenId, sampleUri))
+ .to.emit(this.token, 'MetadataUpdate')
+ .withArgs(tokenId);
+ });
+
+ it('setting the uri for non existent token id is allowed', async function () {
+ await expect(await this.token.$_setTokenURI(nonExistentTokenId, sampleUri))
+ .to.emit(this.token, 'MetadataUpdate')
+ .withArgs(nonExistentTokenId);
+
+ // value will be accessible after mint
+ await this.token.$_mint(this.owner, nonExistentTokenId);
+ expect(await this.token.tokenURI(nonExistentTokenId)).to.equal(sampleUri);
+ });
+
+ it('base URI can be set', async function () {
+ await this.token.setBaseURI(baseURI);
+ expect(await this.token.$_baseURI()).to.equal(baseURI);
+ });
+
+ it('base URI is added as a prefix to the token URI', async function () {
+ await this.token.setBaseURI(baseURI);
+ await this.token.$_setTokenURI(tokenId, sampleUri);
+
+ expect(await this.token.tokenURI(tokenId)).to.equal(baseURI + sampleUri);
+ });
+
+ it('token URI can be changed by changing the base URI', async function () {
+ await this.token.setBaseURI(baseURI);
+ await this.token.$_setTokenURI(tokenId, sampleUri);
+
+ await this.token.setBaseURI(otherBaseURI);
+ expect(await this.token.tokenURI(tokenId)).to.equal(otherBaseURI + sampleUri);
+ });
+
+ it('tokenId is appended to base URI for tokens with no URI', async function () {
+ await this.token.setBaseURI(baseURI);
+
+ expect(await this.token.tokenURI(tokenId)).to.equal(baseURI + tokenId);
+ });
+
+ it('tokens without URI can be burnt ', async function () {
+ await this.token.$_burn(tokenId);
+
+ await expect(this.token.tokenURI(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+ });
+
+ it('tokens with URI can be burnt ', async function () {
+ await this.token.$_setTokenURI(tokenId, sampleUri);
+
+ await this.token.$_burn(tokenId);
+
+ await expect(this.token.tokenURI(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+ });
+
+ it('tokens URI is kept if token is burnt and reminted ', async function () {
+ await this.token.$_setTokenURI(tokenId, sampleUri);
+
+ await this.token.$_burn(tokenId);
+
+ await expect(this.token.tokenURI(tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721NonexistentToken')
+ .withArgs(tokenId);
+
+ await this.token.$_mint(this.owner, tokenId);
+ expect(await this.token.tokenURI(tokenId)).to.equal(sampleUri);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Votes.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Votes.test.js
new file mode 100644
index 000000000..dcae1b8d2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Votes.test.js
@@ -0,0 +1,194 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture, mine } = require('@nomicfoundation/hardhat-network-helpers');
+
+const time = require('../../../helpers/time');
+
+const { shouldBehaveLikeVotes } = require('../../../governance/utils/Votes.behavior');
+
+const TOKENS = [
+ { Token: '$ERC721Votes', mode: 'blocknumber' },
+ // no timestamp mode for ERC721Votes yet
+];
+
+const name = 'My Vote';
+const symbol = 'MTKN';
+const version = '1';
+const tokens = [ethers.parseEther('10000000'), 10n, 20n, 30n];
+
+describe('ERC721Votes', function () {
+ for (const { Token, mode } of TOKENS) {
+ const fixture = async () => {
+ // accounts is required by shouldBehaveLikeVotes
+ const accounts = await ethers.getSigners();
+ const [holder, recipient, other1, other2] = accounts;
+
+ const token = await ethers.deployContract(Token, [name, symbol, name, version]);
+
+ return { accounts, holder, recipient, other1, other2, token };
+ };
+
+ describe(`vote with ${mode}`, function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ this.votes = this.token;
+ });
+
+ // includes ERC6372 behavior check
+ shouldBehaveLikeVotes(tokens, { mode, fungible: false });
+
+ describe('balanceOf', function () {
+ beforeEach(async function () {
+ await this.votes.$_mint(this.holder, tokens[0]);
+ await this.votes.$_mint(this.holder, tokens[1]);
+ await this.votes.$_mint(this.holder, tokens[2]);
+ await this.votes.$_mint(this.holder, tokens[3]);
+ });
+
+ it('grants to initial account', async function () {
+ expect(await this.votes.balanceOf(this.holder)).to.equal(4n);
+ });
+ });
+
+ describe('transfers', function () {
+ beforeEach(async function () {
+ await this.votes.$_mint(this.holder, tokens[0]);
+ });
+
+ it('no delegation', async function () {
+ await expect(this.votes.connect(this.holder).transferFrom(this.holder, this.recipient, tokens[0]))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, tokens[0])
+ .to.not.emit(this.token, 'DelegateVotesChanged');
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 0n;
+ });
+
+ it('sender delegation', async function () {
+ await this.votes.connect(this.holder).delegate(this.holder);
+
+ const tx = await this.votes.connect(this.holder).transferFrom(this.holder, this.recipient, tokens[0]);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, tokens[0])
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, 1n, 0n);
+
+ const { logs } = await tx.wait();
+ const { index } = logs.find(event => event.fragment.name == 'DelegateVotesChanged');
+ for (const event of logs.filter(event => event.fragment.name == 'Transfer')) {
+ expect(event.index).to.lt(index);
+ }
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 0n;
+ });
+
+ it('receiver delegation', async function () {
+ await this.votes.connect(this.recipient).delegate(this.recipient);
+
+ const tx = await this.votes.connect(this.holder).transferFrom(this.holder, this.recipient, tokens[0]);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, tokens[0])
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.recipient, 0n, 1n);
+
+ const { logs } = await tx.wait();
+ const { index } = logs.find(event => event.fragment.name == 'DelegateVotesChanged');
+ for (const event of logs.filter(event => event.fragment.name == 'Transfer')) {
+ expect(event.index).to.lt(index);
+ }
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 1n;
+ });
+
+ it('full delegation', async function () {
+ await this.votes.connect(this.holder).delegate(this.holder);
+ await this.votes.connect(this.recipient).delegate(this.recipient);
+
+ const tx = await this.votes.connect(this.holder).transferFrom(this.holder, this.recipient, tokens[0]);
+ await expect(tx)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.holder, this.recipient, tokens[0])
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.holder, 1n, 0n)
+ .to.emit(this.token, 'DelegateVotesChanged')
+ .withArgs(this.recipient, 0n, 1n);
+
+ const { logs } = await tx.wait();
+ const { index } = logs.find(event => event.fragment.name == 'DelegateVotesChanged');
+ for (const event of logs.filter(event => event.fragment.name == 'Transfer')) {
+ expect(event.index).to.lt(index);
+ }
+
+ this.holderVotes = 0;
+ this.recipientVotes = 1n;
+ });
+
+ it('returns the same total supply on transfers', async function () {
+ await this.votes.connect(this.holder).delegate(this.holder);
+
+ const tx = await this.votes.connect(this.holder).transferFrom(this.holder, this.recipient, tokens[0]);
+ const timepoint = await time.clockFromReceipt[mode](tx);
+
+ await mine(2);
+
+ expect(await this.votes.getPastTotalSupply(timepoint - 1n)).to.equal(1n);
+ expect(await this.votes.getPastTotalSupply(timepoint + 1n)).to.equal(1n);
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 0n;
+ });
+
+ it('generally returns the voting balance at the appropriate checkpoint', async function () {
+ await this.votes.$_mint(this.holder, tokens[1]);
+ await this.votes.$_mint(this.holder, tokens[2]);
+ await this.votes.$_mint(this.holder, tokens[3]);
+
+ const total = await this.votes.balanceOf(this.holder);
+
+ const t1 = await this.votes.connect(this.holder).delegate(this.other1);
+ await mine(2);
+ const t2 = await this.votes.connect(this.holder).transferFrom(this.holder, this.other2, tokens[0]);
+ await mine(2);
+ const t3 = await this.votes.connect(this.holder).transferFrom(this.holder, this.other2, tokens[2]);
+ await mine(2);
+ const t4 = await this.votes.connect(this.other2).transferFrom(this.other2, this.holder, tokens[2]);
+ await mine(2);
+
+ t1.timepoint = await time.clockFromReceipt[mode](t1);
+ t2.timepoint = await time.clockFromReceipt[mode](t2);
+ t3.timepoint = await time.clockFromReceipt[mode](t3);
+ t4.timepoint = await time.clockFromReceipt[mode](t4);
+
+ expect(await this.votes.getPastVotes(this.other1, t1.timepoint - 1n)).to.equal(0n);
+ expect(await this.votes.getPastVotes(this.other1, t1.timepoint)).to.equal(total);
+ expect(await this.votes.getPastVotes(this.other1, t1.timepoint + 1n)).to.equal(total);
+ expect(await this.votes.getPastVotes(this.other1, t2.timepoint)).to.equal(3n);
+ expect(await this.votes.getPastVotes(this.other1, t2.timepoint + 1n)).to.equal(3n);
+ expect(await this.votes.getPastVotes(this.other1, t3.timepoint)).to.equal(2n);
+ expect(await this.votes.getPastVotes(this.other1, t3.timepoint + 1n)).to.equal(2n);
+ expect(await this.votes.getPastVotes(this.other1, t4.timepoint)).to.equal('3');
+ expect(await this.votes.getPastVotes(this.other1, t4.timepoint + 1n)).to.equal(3n);
+
+ this.holderVotes = 0n;
+ this.recipientVotes = 0n;
+ });
+
+ afterEach(async function () {
+ expect(await this.votes.getVotes(this.holder)).to.equal(this.holderVotes);
+ expect(await this.votes.getVotes(this.recipient)).to.equal(this.recipientVotes);
+
+ // need to advance 2 blocks to see the effect of a transfer on "getPastVotes"
+ const timepoint = await time.clock[mode]();
+ await mine();
+ expect(await this.votes.getPastVotes(this.holder, timepoint)).to.equal(this.holderVotes);
+ expect(await this.votes.getPastVotes(this.recipient, timepoint)).to.equal(this.recipientVotes);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Wrapper.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Wrapper.test.js
new file mode 100644
index 000000000..eeead4c1f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/extensions/ERC721Wrapper.test.js
@@ -0,0 +1,201 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldBehaveLikeERC721 } = require('../ERC721.behavior');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+const tokenId = 1n;
+const otherTokenId = 2n;
+
+async function fixture() {
+ const accounts = await ethers.getSigners();
+ const [owner, approved, other] = accounts;
+
+ const underlying = await ethers.deployContract('$ERC721', [name, symbol]);
+ await underlying.$_safeMint(owner, tokenId);
+ await underlying.$_safeMint(owner, otherTokenId);
+ const token = await ethers.deployContract('$ERC721Wrapper', [`Wrapped ${name}`, `W${symbol}`, underlying]);
+
+ return { accounts, owner, approved, other, underlying, token };
+}
+
+describe('ERC721Wrapper', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('has a name', async function () {
+ expect(await this.token.name()).to.equal(`Wrapped ${name}`);
+ });
+
+ it('has a symbol', async function () {
+ expect(await this.token.symbol()).to.equal(`W${symbol}`);
+ });
+
+ it('has underlying', async function () {
+ expect(await this.token.underlying()).to.equal(this.underlying);
+ });
+
+ describe('depositFor', function () {
+ it('works with token approval', async function () {
+ await this.underlying.connect(this.owner).approve(this.token, tokenId);
+
+ await expect(this.token.connect(this.owner).depositFor(this.owner, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.owner, this.token, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.owner, tokenId);
+ });
+
+ it('works with approval for all', async function () {
+ await this.underlying.connect(this.owner).setApprovalForAll(this.token, true);
+
+ await expect(this.token.connect(this.owner).depositFor(this.owner, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.owner, this.token, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.owner, tokenId);
+ });
+
+ it('works sending to another account', async function () {
+ await this.underlying.connect(this.owner).approve(this.token, tokenId);
+
+ await expect(this.token.connect(this.owner).depositFor(this.other, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.owner, this.token, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.other, tokenId);
+ });
+
+ it('works with multiple tokens', async function () {
+ await this.underlying.connect(this.owner).approve(this.token, tokenId);
+ await this.underlying.connect(this.owner).approve(this.token, otherTokenId);
+
+ await expect(this.token.connect(this.owner).depositFor(this.owner, [tokenId, otherTokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.owner, this.token, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.owner, tokenId)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.owner, this.token, otherTokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.owner, otherTokenId);
+ });
+
+ it('reverts with missing approval', async function () {
+ await expect(this.token.connect(this.owner).depositFor(this.owner, [tokenId]))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InsufficientApproval')
+ .withArgs(this.token, tokenId);
+ });
+ });
+
+ describe('withdrawTo', function () {
+ beforeEach(async function () {
+ await this.underlying.connect(this.owner).approve(this.token, tokenId);
+ await this.token.connect(this.owner).depositFor(this.owner, [tokenId]);
+ });
+
+ it('works for an owner', async function () {
+ await expect(this.token.connect(this.owner).withdrawTo(this.owner, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.owner, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId);
+ });
+
+ it('works for an approved', async function () {
+ await this.token.connect(this.owner).approve(this.approved, tokenId);
+
+ await expect(this.token.connect(this.approved).withdrawTo(this.owner, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.owner, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId);
+ });
+
+ it('works for an approved for all', async function () {
+ await this.token.connect(this.owner).setApprovalForAll(this.approved, true);
+
+ await expect(this.token.connect(this.approved).withdrawTo(this.owner, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.owner, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId);
+ });
+
+ it("doesn't work for a non-owner nor approved", async function () {
+ await expect(this.token.connect(this.other).withdrawTo(this.owner, [tokenId]))
+ .to.be.revertedWithCustomError(this.token, 'ERC721InsufficientApproval')
+ .withArgs(this.other, tokenId);
+ });
+
+ it('works with multiple tokens', async function () {
+ await this.underlying.connect(this.owner).approve(this.token, otherTokenId);
+ await this.token.connect(this.owner).depositFor(this.owner, [otherTokenId]);
+
+ await expect(this.token.connect(this.owner).withdrawTo(this.owner, [tokenId, otherTokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.owner, tokenId)
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.owner, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId);
+ });
+
+ it('works to another account', async function () {
+ await expect(this.token.connect(this.owner).withdrawTo(this.other, [tokenId]))
+ .to.emit(this.underlying, 'Transfer')
+ .withArgs(this.token, this.other, tokenId)
+ .to.emit(this.token, 'Transfer')
+ .withArgs(this.owner, ethers.ZeroAddress, tokenId);
+ });
+ });
+
+ describe('onERC721Received', function () {
+ it('only allows calls from underlying', async function () {
+ await expect(
+ this.token.connect(this.other).onERC721Received(
+ this.owner,
+ this.token,
+ tokenId,
+ this.other.address, // Correct data
+ ),
+ )
+ .to.be.revertedWithCustomError(this.token, 'ERC721UnsupportedToken')
+ .withArgs(this.other);
+ });
+
+ it('mints a token to from', async function () {
+ await expect(this.underlying.connect(this.owner).safeTransferFrom(this.owner, this.token, tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.owner, tokenId);
+ });
+ });
+
+ describe('_recover', function () {
+ it('works if there is something to recover', async function () {
+ // Should use `transferFrom` to avoid `onERC721Received` minting
+ await this.underlying.connect(this.owner).transferFrom(this.owner, this.token, tokenId);
+
+ await expect(this.token.$_recover(this.other, tokenId))
+ .to.emit(this.token, 'Transfer')
+ .withArgs(ethers.ZeroAddress, this.other, tokenId);
+ });
+
+ it('reverts if there is nothing to recover', async function () {
+ const holder = await this.underlying.ownerOf(tokenId);
+
+ await expect(this.token.$_recover(holder, tokenId))
+ .to.be.revertedWithCustomError(this.token, 'ERC721IncorrectOwner')
+ .withArgs(this.token, tokenId, holder);
+ });
+ });
+
+ describe('ERC712 behavior', function () {
+ shouldBehaveLikeERC721();
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Holder.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Holder.test.js
new file mode 100644
index 000000000..31dd2fd20
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Holder.test.js
@@ -0,0 +1,20 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+const name = 'Non Fungible Token';
+const symbol = 'NFT';
+const tokenId = 1n;
+
+describe('ERC721Holder', function () {
+ it('receives an ERC721 token', async function () {
+ const [owner] = await ethers.getSigners();
+
+ const token = await ethers.deployContract('$ERC721', [name, symbol]);
+ await token.$_mint(owner, tokenId);
+
+ const receiver = await ethers.deployContract('$ERC721Holder');
+ await token.connect(owner).safeTransferFrom(owner, receiver, tokenId);
+
+ expect(await token.ownerOf(tokenId)).to.equal(receiver);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Utils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Utils.test.js
new file mode 100644
index 000000000..2327d1ac7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/ERC721/utils/ERC721Utils.test.js
@@ -0,0 +1,94 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { RevertType } = require('../../../helpers/enums');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const tokenId = 1n;
+
+const RECEIVER_MAGIC_VALUE = '0x150b7a02';
+
+const deployReceiver = (revertType, returnValue = RECEIVER_MAGIC_VALUE) =>
+ ethers.deployContract('$ERC721ReceiverMock', [returnValue, revertType]);
+
+const fixture = async () => {
+ const [eoa, operator, owner] = await ethers.getSigners();
+ const utils = await ethers.deployContract('$ERC721Utils');
+
+ const receivers = {
+ correct: await deployReceiver(RevertType.None),
+ invalid: await deployReceiver(RevertType.None, '0xdeadbeef'),
+ message: await deployReceiver(RevertType.RevertWithMessage),
+ empty: await deployReceiver(RevertType.RevertWithoutMessage),
+ customError: await deployReceiver(RevertType.RevertWithCustomError),
+ panic: await deployReceiver(RevertType.Panic),
+ nonReceiver: await ethers.deployContract('CallReceiverMock'),
+ eoa,
+ };
+
+ return { operator, owner, utils, receivers };
+};
+
+describe('ERC721Utils', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('onERC721Received', function () {
+ it('succeeds when called by an EOA', async function () {
+ await expect(this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.eoa, tokenId, '0x')).to
+ .not.be.reverted;
+ });
+
+ it('succeeds when data is passed', async function () {
+ const data = '0x12345678';
+ await expect(this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.correct, tokenId, data))
+ .to.not.be.reverted;
+ });
+
+ it('succeeds when data is empty', async function () {
+ await expect(this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.correct, tokenId, '0x'))
+ .to.not.be.reverted;
+ });
+
+ it('reverts when receiver returns invalid value', async function () {
+ await expect(this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.invalid, tokenId, '0x'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC721InvalidReceiver')
+ .withArgs(this.receivers.invalid);
+ });
+
+ it('reverts when receiver reverts with message', async function () {
+ await expect(
+ this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.message, tokenId, '0x'),
+ ).to.be.revertedWith('ERC721ReceiverMock: reverting');
+ });
+
+ it('reverts when receiver reverts without message', async function () {
+ await expect(this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.empty, tokenId, '0x'))
+ .to.be.revertedWithCustomError(this.utils, 'ERC721InvalidReceiver')
+ .withArgs(this.receivers.empty);
+ });
+
+ it('reverts when receiver reverts with custom error', async function () {
+ await expect(
+ this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.customError, tokenId, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.receivers.customError, 'CustomError')
+ .withArgs(RECEIVER_MAGIC_VALUE);
+ });
+
+ it('reverts when receiver panics', async function () {
+ await expect(
+ this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.panic, tokenId, '0x'),
+ ).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+
+ it('reverts when receiver does not implement onERC721Received', async function () {
+ await expect(
+ this.utils.$checkOnERC721Received(this.operator, this.owner, this.receivers.nonReceiver, tokenId, '0x'),
+ )
+ .to.be.revertedWithCustomError(this.utils, 'ERC721InvalidReceiver')
+ .withArgs(this.receivers.nonReceiver);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/common/ERC2981.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/common/ERC2981.behavior.js
new file mode 100644
index 000000000..ae6abccae
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/token/common/ERC2981.behavior.js
@@ -0,0 +1,152 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior');
+
+function shouldBehaveLikeERC2981() {
+ const royaltyFraction = 10n;
+
+ shouldSupportInterfaces(['ERC2981']);
+
+ describe('default royalty', function () {
+ beforeEach(async function () {
+ await this.token.$_setDefaultRoyalty(this.account1, royaltyFraction);
+ });
+
+ it('checks royalty is set', async function () {
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([
+ this.account1.address,
+ (this.salePrice * royaltyFraction) / 10_000n,
+ ]);
+ });
+
+ it('updates royalty amount', async function () {
+ const newFraction = 25n;
+
+ await this.token.$_setDefaultRoyalty(this.account1, newFraction);
+
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([
+ this.account1.address,
+ (this.salePrice * newFraction) / 10_000n,
+ ]);
+ });
+
+ it('holds same royalty value for different tokens', async function () {
+ const newFraction = 20n;
+
+ await this.token.$_setDefaultRoyalty(this.account1, newFraction);
+
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal(
+ await this.token.royaltyInfo(this.tokenId2, this.salePrice),
+ );
+ });
+
+ it('Remove royalty information', async function () {
+ const newValue = 0n;
+ await this.token.$_deleteDefaultRoyalty();
+
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ethers.ZeroAddress, newValue]);
+
+ expect(await this.token.royaltyInfo(this.tokenId2, this.salePrice)).to.deep.equal([ethers.ZeroAddress, newValue]);
+ });
+
+ it('reverts if invalid parameters', async function () {
+ const royaltyDenominator = await this.token.$_feeDenominator();
+
+ await expect(this.token.$_setDefaultRoyalty(ethers.ZeroAddress, royaltyFraction))
+ .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidDefaultRoyaltyReceiver')
+ .withArgs(ethers.ZeroAddress);
+
+ const anotherRoyaltyFraction = 11000n;
+
+ await expect(this.token.$_setDefaultRoyalty(this.account1, anotherRoyaltyFraction))
+ .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidDefaultRoyalty')
+ .withArgs(anotherRoyaltyFraction, royaltyDenominator);
+ });
+ });
+
+ describe('token based royalty', function () {
+ beforeEach(async function () {
+ await this.token.$_setTokenRoyalty(this.tokenId1, this.account1, royaltyFraction);
+ });
+
+ it('updates royalty amount', async function () {
+ const newFraction = 25n;
+
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([
+ this.account1.address,
+ (this.salePrice * royaltyFraction) / 10_000n,
+ ]);
+
+ await this.token.$_setTokenRoyalty(this.tokenId1, this.account1, newFraction);
+
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([
+ this.account1.address,
+ (this.salePrice * newFraction) / 10_000n,
+ ]);
+ });
+
+ it('holds different values for different tokens', async function () {
+ const newFraction = 20n;
+
+ await this.token.$_setTokenRoyalty(this.tokenId2, this.account1, newFraction);
+
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.not.deep.equal(
+ await this.token.royaltyInfo(this.tokenId2, this.salePrice),
+ );
+ });
+
+ it('reverts if invalid parameters', async function () {
+ const royaltyDenominator = await this.token.$_feeDenominator();
+
+ await expect(this.token.$_setTokenRoyalty(this.tokenId1, ethers.ZeroAddress, royaltyFraction))
+ .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidTokenRoyaltyReceiver')
+ .withArgs(this.tokenId1, ethers.ZeroAddress);
+
+ const anotherRoyaltyFraction = 11000n;
+
+ await expect(this.token.$_setTokenRoyalty(this.tokenId1, this.account1, anotherRoyaltyFraction))
+ .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidTokenRoyalty')
+ .withArgs(this.tokenId1, anotherRoyaltyFraction, royaltyDenominator);
+ });
+
+ it('can reset token after setting royalty', async function () {
+ const newFraction = 30n;
+
+ await this.token.$_setTokenRoyalty(this.tokenId1, this.account2, newFraction);
+
+ // Tokens must have own information
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([
+ this.account2.address,
+ (this.salePrice * newFraction) / 10_000n,
+ ]);
+
+ await this.token.$_setTokenRoyalty(this.tokenId2, this.account1, 0n);
+
+ // Token must not share default information
+ expect(await this.token.royaltyInfo(this.tokenId2, this.salePrice)).to.deep.equal([this.account1.address, 0n]);
+ });
+
+ it('can hold default and token royalty information', async function () {
+ const newFraction = 30n;
+
+ await this.token.$_setTokenRoyalty(this.tokenId2, this.account2, newFraction);
+
+ // Tokens must not have same values
+ expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.not.deep.equal([
+ this.account2.address,
+ (this.salePrice * newFraction) / 10_000n,
+ ]);
+
+ // Updated token must have new values
+ expect(await this.token.royaltyInfo(this.tokenId2, this.salePrice)).to.deep.equal([
+ this.account2.address,
+ (this.salePrice * newFraction) / 10_000n,
+ ]);
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeERC2981,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Address.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Address.test.js
new file mode 100644
index 000000000..8307a923e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Address.test.js
@@ -0,0 +1,281 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const coder = ethers.AbiCoder.defaultAbiCoder();
+
+async function fixture() {
+ const [recipient, other] = await ethers.getSigners();
+
+ const mock = await ethers.deployContract('$Address');
+ const target = await ethers.deployContract('CallReceiverMock');
+ const targetEther = await ethers.deployContract('EtherReceiverMock');
+
+ return { recipient, other, mock, target, targetEther };
+}
+
+describe('Address', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('sendValue', function () {
+ describe('when sender contract has no funds', function () {
+ it('sends 0 wei', async function () {
+ await expect(this.mock.$sendValue(this.other, 0n)).to.changeEtherBalance(this.recipient, 0n);
+ });
+
+ it('reverts when sending non-zero amounts', async function () {
+ await expect(this.mock.$sendValue(this.other, 1n))
+ .to.be.revertedWithCustomError(this.mock, 'InsufficientBalance')
+ .withArgs(0n, 1n);
+ });
+ });
+
+ describe('when sender contract has funds', function () {
+ const funds = ethers.parseEther('1');
+
+ beforeEach(async function () {
+ await this.other.sendTransaction({ to: this.mock, value: funds });
+ });
+
+ describe('with EOA recipient', function () {
+ it('sends 0 wei', async function () {
+ await expect(this.mock.$sendValue(this.recipient, 0n)).to.changeEtherBalance(this.recipient, 0n);
+ });
+
+ it('sends non-zero amounts', async function () {
+ await expect(this.mock.$sendValue(this.recipient, funds - 1n)).to.changeEtherBalance(
+ this.recipient,
+ funds - 1n,
+ );
+ });
+
+ it('sends the whole balance', async function () {
+ await expect(this.mock.$sendValue(this.recipient, funds)).to.changeEtherBalance(this.recipient, funds);
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+ });
+
+ it('reverts when sending more than the balance', async function () {
+ await expect(this.mock.$sendValue(this.recipient, funds + 1n))
+ .to.be.revertedWithCustomError(this.mock, 'InsufficientBalance')
+ .withArgs(funds, funds + 1n);
+ });
+ });
+
+ describe('with contract recipient', function () {
+ it('sends funds', async function () {
+ await this.targetEther.setAcceptEther(true);
+ await expect(this.mock.$sendValue(this.targetEther, funds)).to.changeEtherBalance(this.targetEther, funds);
+ });
+
+ it('reverts on recipient revert', async function () {
+ await this.targetEther.setAcceptEther(false);
+ await expect(this.mock.$sendValue(this.targetEther, funds)).to.be.revertedWithCustomError(
+ this.mock,
+ 'FailedCall',
+ );
+ });
+ });
+ });
+ });
+
+ describe('functionCall', function () {
+ describe('with valid contract receiver', function () {
+ it('calls the requested function', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionCall(this.target, call))
+ .to.emit(this.target, 'MockFunctionCalled')
+ .to.emit(this.mock, 'return$functionCall')
+ .withArgs(coder.encode(['string'], ['0x1234']));
+ });
+
+ it('calls the requested empty return function', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionEmptyReturn');
+
+ await expect(this.mock.$functionCall(this.target, call)).to.emit(this.target, 'MockFunctionCalled');
+ });
+
+ it('reverts when the called function reverts with no reason', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionRevertsNoReason');
+
+ await expect(this.mock.$functionCall(this.target, call)).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+ });
+
+ it('reverts when the called function reverts, bubbling up the revert reason', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionRevertsReason');
+
+ await expect(this.mock.$functionCall(this.target, call)).to.be.revertedWith('CallReceiverMock: reverting');
+ });
+
+ it('reverts when the called function runs out of gas', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionOutOfGas');
+
+ await expect(this.mock.$functionCall(this.target, call, { gasLimit: 120_000n })).to.be.revertedWithCustomError(
+ this.mock,
+ 'FailedCall',
+ );
+ });
+
+ it('reverts when the called function throws', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionThrows');
+
+ await expect(this.mock.$functionCall(this.target, call)).to.be.revertedWithPanic(PANIC_CODES.ASSERTION_ERROR);
+ });
+
+ it('reverts when function does not exist', async function () {
+ const call = new ethers.Interface(['function mockFunctionDoesNotExist()']).encodeFunctionData(
+ 'mockFunctionDoesNotExist',
+ );
+
+ await expect(this.mock.$functionCall(this.target, call)).to.be.revertedWithCustomError(this.mock, 'FailedCall');
+ });
+ });
+
+ describe('with non-contract receiver', function () {
+ it('reverts when address is not a contract', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionCall(this.recipient, call))
+ .to.be.revertedWithCustomError(this.mock, 'AddressEmptyCode')
+ .withArgs(this.recipient);
+ });
+ });
+ });
+
+ describe('functionCallWithValue', function () {
+ describe('with zero value', function () {
+ it('calls the requested function', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionCallWithValue(this.target, call, 0n))
+ .to.emit(this.target, 'MockFunctionCalled')
+ .to.emit(this.mock, 'return$functionCallWithValue')
+ .withArgs(coder.encode(['string'], ['0x1234']));
+ });
+ });
+
+ describe('with non-zero value', function () {
+ const value = ethers.parseEther('1.2');
+
+ it('reverts if insufficient sender balance', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionCallWithValue(this.target, call, value))
+ .to.be.revertedWithCustomError(this.mock, 'InsufficientBalance')
+ .withArgs(0n, value);
+ });
+
+ it('calls the requested function with existing value', async function () {
+ await this.other.sendTransaction({ to: this.mock, value });
+
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+ const tx = await this.mock.$functionCallWithValue(this.target, call, value);
+
+ await expect(tx).to.changeEtherBalance(this.target, value);
+
+ await expect(tx)
+ .to.emit(this.target, 'MockFunctionCalled')
+ .to.emit(this.mock, 'return$functionCallWithValue')
+ .withArgs(coder.encode(['string'], ['0x1234']));
+ });
+
+ it('calls the requested function with transaction funds', async function () {
+ expect(await ethers.provider.getBalance(this.mock)).to.equal(0n);
+
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+ const tx = await this.mock.connect(this.other).$functionCallWithValue(this.target, call, value, { value });
+
+ await expect(tx).to.changeEtherBalance(this.target, value);
+ await expect(tx)
+ .to.emit(this.target, 'MockFunctionCalled')
+ .to.emit(this.mock, 'return$functionCallWithValue')
+ .withArgs(coder.encode(['string'], ['0x1234']));
+ });
+
+ it('reverts when calling non-payable functions', async function () {
+ await this.other.sendTransaction({ to: this.mock, value });
+
+ const call = this.target.interface.encodeFunctionData('mockFunctionNonPayable');
+
+ await expect(this.mock.$functionCallWithValue(this.target, call, value)).to.be.revertedWithCustomError(
+ this.mock,
+ 'FailedCall',
+ );
+ });
+ });
+ });
+
+ describe('functionStaticCall', function () {
+ it('calls the requested function', async function () {
+ const call = this.target.interface.encodeFunctionData('mockStaticFunction');
+
+ expect(await this.mock.$functionStaticCall(this.target, call)).to.equal(coder.encode(['string'], ['0x1234']));
+ });
+
+ it('reverts on a non-static function', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionStaticCall(this.target, call)).to.be.revertedWithCustomError(
+ this.mock,
+ 'FailedCall',
+ );
+ });
+
+ it('bubbles up revert reason', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionRevertsReason');
+
+ await expect(this.mock.$functionStaticCall(this.target, call)).to.be.revertedWith('CallReceiverMock: reverting');
+ });
+
+ it('reverts when address is not a contract', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionStaticCall(this.recipient, call))
+ .to.be.revertedWithCustomError(this.mock, 'AddressEmptyCode')
+ .withArgs(this.recipient);
+ });
+ });
+
+ describe('functionDelegateCall', function () {
+ it('delegate calls the requested function', async function () {
+ const slot = ethers.hexlify(ethers.randomBytes(32));
+ const value = ethers.hexlify(ethers.randomBytes(32));
+
+ const call = this.target.interface.encodeFunctionData('mockFunctionWritesStorage', [slot, value]);
+
+ expect(await ethers.provider.getStorage(this.mock, slot)).to.equal(ethers.ZeroHash);
+
+ await expect(await this.mock.$functionDelegateCall(this.target, call))
+ .to.emit(this.mock, 'return$functionDelegateCall')
+ .withArgs(coder.encode(['string'], ['0x1234']));
+
+ expect(await ethers.provider.getStorage(this.mock, slot)).to.equal(value);
+ });
+
+ it('bubbles up revert reason', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunctionRevertsReason');
+
+ await expect(this.mock.$functionDelegateCall(this.target, call)).to.be.revertedWith(
+ 'CallReceiverMock: reverting',
+ );
+ });
+
+ it('reverts when address is not a contract', async function () {
+ const call = this.target.interface.encodeFunctionData('mockFunction');
+
+ await expect(this.mock.$functionDelegateCall(this.recipient, call))
+ .to.be.revertedWithCustomError(this.mock, 'AddressEmptyCode')
+ .withArgs(this.recipient);
+ });
+ });
+
+ describe('verifyCallResult', function () {
+ it('returns returndata on success', async function () {
+ const returndata = '0x123abc';
+ expect(await this.mock.$verifyCallResult(true, returndata)).to.equal(returndata);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Arrays.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Arrays.t.sol
new file mode 100644
index 000000000..09c7b66b6
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Arrays.t.sol
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {SymTest} from "halmos-cheatcodes/SymTest.sol";
+import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol";
+
+contract ArraysTest is Test, SymTest {
+ function testSort(uint256[] memory values) public {
+ Arrays.sort(values);
+ _assertSort(values);
+ }
+
+ function symbolicSort() public {
+ uint256[] memory values = new uint256[](3);
+ for (uint256 i = 0; i < 3; i++) {
+ values[i] = svm.createUint256("arrayElement");
+ }
+ Arrays.sort(values);
+ _assertSort(values);
+ }
+
+ /// Asserts
+
+ function _assertSort(uint256[] memory values) internal {
+ for (uint256 i = 1; i < values.length; ++i) {
+ assertLe(values[i - 1], values[i]);
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Arrays.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Arrays.test.js
new file mode 100644
index 000000000..bcb385897
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Arrays.test.js
@@ -0,0 +1,223 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { generators } = require('../helpers/random');
+const { capitalize } = require('../../scripts/helpers');
+const { TYPES } = require('../../scripts/generate/templates/Arrays.opts');
+
+// See https://en.cppreference.com/w/cpp/algorithm/lower_bound
+const lowerBound = (array, value) => {
+ const i = array.findIndex(element => value <= element);
+ return i == -1 ? array.length : i;
+};
+
+// See https://en.cppreference.com/w/cpp/algorithm/upper_bound
+const upperBound = (array, value) => {
+ const i = array.findIndex(element => value < element);
+ return i == -1 ? array.length : i;
+};
+
+const bigintSign = x => (x > 0n ? 1 : x < 0n ? -1 : 0);
+const comparator = (a, b) => bigintSign(ethers.toBigInt(a) - ethers.toBigInt(b));
+const hasDuplicates = array => array.some((v, i) => array.indexOf(v) != i);
+
+describe('Arrays', function () {
+ const fixture = async () => {
+ return { mock: await ethers.deployContract('$Arrays') };
+ };
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('search', function () {
+ for (const [title, { array, tests }] of Object.entries({
+ 'Even number of elements': {
+ array: [11n, 12n, 13n, 14n, 15n, 16n, 17n, 18n, 19n, 20n],
+ tests: {
+ 'basic case': 16n,
+ 'first element': 11n,
+ 'last element': 20n,
+ 'searched value is over the upper boundary': 32n,
+ 'searched value is under the lower boundary': 2n,
+ },
+ },
+ 'Odd number of elements': {
+ array: [11n, 12n, 13n, 14n, 15n, 16n, 17n, 18n, 19n, 20n, 21n],
+ tests: {
+ 'basic case': 16n,
+ 'first element': 11n,
+ 'last element': 21n,
+ 'searched value is over the upper boundary': 32n,
+ 'searched value is under the lower boundary': 2n,
+ },
+ },
+ 'Array with gap': {
+ array: [11n, 12n, 13n, 14n, 15n, 20n, 21n, 22n, 23n, 24n],
+ tests: {
+ 'search value in gap': 17n,
+ },
+ },
+ 'Array with duplicated elements': {
+ array: [0n, 10n, 10n, 10n, 10n, 10n, 10n, 10n, 20n],
+ tests: {
+ 'search value is duplicated': 10n,
+ },
+ },
+ 'Array with duplicated first element': {
+ array: [10n, 10n, 10n, 10n, 10n, 10n, 10n, 20n],
+ tests: {
+ 'search value is duplicated first element': 10n,
+ },
+ },
+ 'Array with duplicated last element': {
+ array: [0n, 10n, 10n, 10n, 10n, 10n, 10n, 10n],
+ tests: {
+ 'search value is duplicated last element': 10n,
+ },
+ },
+ 'Empty array': {
+ array: [],
+ tests: {
+ 'always returns 0 for empty array': 10n,
+ },
+ },
+ })) {
+ describe(title, function () {
+ const fixture = async () => {
+ return { instance: await ethers.deployContract('Uint256ArraysMock', [array]) };
+ };
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const [name, input] of Object.entries(tests)) {
+ describe(name, function () {
+ it('[deprecated] findUpperBound', async function () {
+ // findUpperBound does not support duplicated
+ if (hasDuplicates(array)) {
+ expect(await this.instance.findUpperBound(input)).to.equal(upperBound(array, input) - 1);
+ } else {
+ expect(await this.instance.findUpperBound(input)).to.equal(lowerBound(array, input));
+ }
+ });
+
+ it('lowerBound', async function () {
+ expect(await this.instance.lowerBound(input)).to.equal(lowerBound(array, input));
+ expect(await this.instance.lowerBoundMemory(array, input)).to.equal(lowerBound(array, input));
+ });
+
+ it('upperBound', async function () {
+ expect(await this.instance.upperBound(input)).to.equal(upperBound(array, input));
+ expect(await this.instance.upperBoundMemory(array, input)).to.equal(upperBound(array, input));
+ });
+ });
+ }
+ });
+ }
+ });
+
+ for (const type of TYPES) {
+ const elements = Array.from({ length: 10 }, generators[type]);
+
+ describe(type, function () {
+ const fixture = async () => {
+ return { instance: await ethers.deployContract(`${capitalize(type)}ArraysMock`, [elements]) };
+ };
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('sort', function () {
+ for (const length of [0, 1, 2, 8, 32, 128]) {
+ describe(`${type}[] of length ${length}`, function () {
+ beforeEach(async function () {
+ this.array = Array.from({ length }, generators[type]);
+ });
+
+ afterEach(async function () {
+ const expected = Array.from(this.array).sort(comparator);
+ const reversed = Array.from(expected).reverse();
+ expect(await this.instance.sort(this.array)).to.deep.equal(expected);
+ expect(await this.instance.sortReverse(this.array)).to.deep.equal(reversed);
+ });
+
+ it('sort array', async function () {
+ // nothing to do here, beforeEach and afterEach already take care of everything.
+ });
+
+ if (length > 1) {
+ it('sort array for identical elements', async function () {
+ // duplicate the first value to all elements
+ this.array.fill(this.array.at(0));
+ });
+
+ it('sort already sorted array', async function () {
+ // pre-sort the elements
+ this.array.sort(comparator);
+ });
+
+ it('sort reversed array', async function () {
+ // pre-sort in reverse order
+ this.array.sort(comparator).reverse();
+ });
+
+ it('sort almost sorted array', async function () {
+ // pre-sort + rotate (move the last element to the front) for an almost sorted effect
+ this.array.sort(comparator);
+ this.array.unshift(this.array.pop());
+ });
+ }
+ });
+ }
+ });
+
+ describe('unsafeAccess', function () {
+ describe('storage', function () {
+ for (const i in elements) {
+ it(`unsafeAccess within bounds #${i}`, async function () {
+ expect(await this.instance.unsafeAccess(i)).to.equal(elements[i]);
+ });
+ }
+
+ it('unsafeAccess outside bounds', async function () {
+ await expect(this.instance.unsafeAccess(elements.length)).to.not.be.rejected;
+ });
+
+ it('unsafeSetLength changes the length or the array', async function () {
+ const newLength = generators.uint256();
+
+ expect(await this.instance.length()).to.equal(elements.length);
+ await expect(this.instance.unsafeSetLength(newLength)).to.not.be.rejected;
+ expect(await this.instance.length()).to.equal(newLength);
+ });
+ });
+
+ describe('memory', function () {
+ const fragment = `$unsafeMemoryAccess(${type}[] arr, uint256 pos)`;
+
+ for (const i in elements) {
+ it(`unsafeMemoryAccess within bounds #${i}`, async function () {
+ expect(await this.mock[fragment](elements, i)).to.equal(elements[i]);
+ });
+ }
+
+ it('unsafeMemoryAccess outside bounds', async function () {
+ await expect(this.mock[fragment](elements, elements.length)).to.not.be.rejected;
+ });
+
+ it('unsafeMemoryAccess loop around', async function () {
+ for (let i = 251n; i < 256n; ++i) {
+ expect(await this.mock[fragment](elements, 2n ** i - 1n)).to.equal(BigInt(elements.length));
+ expect(await this.mock[fragment](elements, 2n ** i + 0n)).to.equal(elements[0]);
+ expect(await this.mock[fragment](elements, 2n ** i + 1n)).to.equal(elements[1]);
+ }
+ });
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Base64.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Base64.t.sol
new file mode 100644
index 000000000..021ae03af
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Base64.t.sol
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Base64} from "@openzeppelin/contracts/utils/Base64.sol";
+
+contract Base64Test is Test {
+ function testEncode(bytes memory input) external {
+ assertEq(Base64.encode(input), vm.toBase64(input));
+ }
+
+ function testEncodeURL(bytes memory input) external {
+ assertEq(Base64.encodeURL(input), _removePadding(vm.toBase64URL(input)));
+ }
+
+ function _removePadding(string memory inputStr) internal pure returns (string memory) {
+ bytes memory input = bytes(inputStr);
+ bytes memory output;
+
+ for (uint256 i = 0; i < input.length; ++i) {
+ if (input[input.length - i - 1] != 0x3d) {
+ output = new bytes(input.length - i);
+ break;
+ }
+ }
+
+ for (uint256 i = 0; i < output.length; ++i) {
+ output[i] = input[i];
+ }
+
+ return string(output);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Base64.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Base64.test.js
new file mode 100644
index 000000000..5c4274666
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Base64.test.js
@@ -0,0 +1,59 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+// Replace "+/" with "-_" in the char table, and remove the padding
+// see https://datatracker.ietf.org/doc/html/rfc4648#section-5
+const base64toBase64Url = str => str.replaceAll('+', '-').replaceAll('/', '_').replaceAll('=', '');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Base64');
+ return { mock };
+}
+
+describe('Strings', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('base64', function () {
+ for (const { title, input, expected } of [
+ { title: 'converts to base64 encoded string with double padding', input: 'test', expected: 'dGVzdA==' },
+ { title: 'converts to base64 encoded string with single padding', input: 'test1', expected: 'dGVzdDE=' },
+ { title: 'converts to base64 encoded string without padding', input: 'test12', expected: 'dGVzdDEy' },
+ { title: 'converts to base64 encoded string (/ case)', input: 'où', expected: 'b/k=' },
+ { title: 'converts to base64 encoded string (+ case)', input: 'zs~1t8', expected: 'enN+MXQ4' },
+ { title: 'empty bytes', input: '', expected: '' },
+ ])
+ it(title, async function () {
+ const buffer = Buffer.from(input, 'ascii');
+ expect(await this.mock.$encode(buffer)).to.equal(ethers.encodeBase64(buffer));
+ expect(await this.mock.$encode(buffer)).to.equal(expected);
+ });
+ });
+
+ describe('base64url', function () {
+ for (const { title, input, expected } of [
+ { title: 'converts to base64url encoded string with double padding', input: 'test', expected: 'dGVzdA' },
+ { title: 'converts to base64url encoded string with single padding', input: 'test1', expected: 'dGVzdDE' },
+ { title: 'converts to base64url encoded string without padding', input: 'test12', expected: 'dGVzdDEy' },
+ { title: 'converts to base64url encoded string (_ case)', input: 'où', expected: 'b_k' },
+ { title: 'converts to base64url encoded string (- case)', input: 'zs~1t8', expected: 'enN-MXQ4' },
+ { title: 'empty bytes', input: '', expected: '' },
+ ])
+ it(title, async function () {
+ const buffer = Buffer.from(input, 'ascii');
+ expect(await this.mock.$encodeURL(buffer)).to.equal(base64toBase64Url(ethers.encodeBase64(buffer)));
+ expect(await this.mock.$encodeURL(buffer)).to.equal(expected);
+ });
+ });
+
+ it('Encode reads beyond the input buffer into dirty memory', async function () {
+ const mock = await ethers.deployContract('Base64Dirty');
+ const buffer32 = ethers.id('example');
+ const buffer31 = buffer32.slice(0, -2);
+
+ expect(await mock.encode(buffer31)).to.equal(ethers.encodeBase64(buffer31));
+ expect(await mock.encode(buffer32)).to.equal(ethers.encodeBase64(buffer32));
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Bytes.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Bytes.test.js
new file mode 100644
index 000000000..52a1ae95e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Bytes.test.js
@@ -0,0 +1,88 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Bytes');
+ return { mock };
+}
+
+const lorem = ethers.toUtf8Bytes(
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+);
+const present = lorem.at(1);
+const absent = 255;
+
+describe('Bytes', function () {
+ before(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('indexOf', function () {
+ it('first', async function () {
+ expect(await this.mock.$indexOf(lorem, ethers.toBeHex(present))).to.equal(lorem.indexOf(present));
+ });
+
+ it('from index', async function () {
+ for (const start in Array(lorem.length + 10).fill()) {
+ const index = lorem.indexOf(present, start);
+ const result = index === -1 ? ethers.MaxUint256 : index;
+ expect(await this.mock.$indexOf(lorem, ethers.toBeHex(present), ethers.Typed.uint256(start))).to.equal(result);
+ }
+ });
+
+ it('absent', async function () {
+ expect(await this.mock.$indexOf(lorem, ethers.toBeHex(absent))).to.equal(ethers.MaxUint256);
+ });
+ });
+
+ describe('lastIndexOf', function () {
+ it('first', async function () {
+ expect(await this.mock.$lastIndexOf(lorem, ethers.toBeHex(present))).to.equal(lorem.lastIndexOf(present));
+ });
+
+ it('from index', async function () {
+ for (const start in Array(lorem.length + 10).fill()) {
+ const index = lorem.lastIndexOf(present, start);
+ const result = index === -1 ? ethers.MaxUint256 : index;
+ expect(await this.mock.$lastIndexOf(lorem, ethers.toBeHex(present), ethers.Typed.uint256(start))).to.equal(
+ result,
+ );
+ }
+ });
+
+ it('absent', async function () {
+ expect(await this.mock.$lastIndexOf(lorem, ethers.toBeHex(absent))).to.equal(ethers.MaxUint256);
+ });
+ });
+
+ describe('slice', function () {
+ describe('slice(bytes, uint256)', function () {
+ for (const [descr, start] of Object.entries({
+ 'start = 0': 0,
+ 'start within bound': 10,
+ 'start out of bound': 1000,
+ })) {
+ it(descr, async function () {
+ const result = ethers.hexlify(lorem.slice(start));
+ expect(await this.mock.$slice(lorem, start)).to.equal(result);
+ });
+ }
+ });
+
+ describe('slice(bytes, uint256, uint256)', function () {
+ for (const [descr, [start, end]] of Object.entries({
+ 'start = 0': [0, 42],
+ 'start and end within bound': [17, 42],
+ 'end out of bound': [42, 1000],
+ 'start = end': [17, 17],
+ 'start > end': [42, 17],
+ })) {
+ it(descr, async function () {
+ const result = ethers.hexlify(lorem.slice(start, end));
+ expect(await this.mock.$slice(lorem, start, ethers.Typed.uint256(end))).to.equal(result);
+ });
+ }
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/CAIP.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/CAIP.test.js
new file mode 100644
index 000000000..cd5995cad
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/CAIP.test.js
@@ -0,0 +1,53 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { CHAINS, getLocalCAIP } = require('../helpers/chains');
+
+async function fixture() {
+ const caip2 = await ethers.deployContract('$CAIP2');
+ const caip10 = await ethers.deployContract('$CAIP10');
+ return { caip2, caip10 };
+}
+
+describe('CAIP utilities', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('CAIP-2', function () {
+ it('local()', async function () {
+ const { caip2 } = await getLocalCAIP();
+ expect(await this.caip2.$local()).to.equal(caip2);
+ });
+
+ for (const { namespace, reference, caip2 } of Object.values(CHAINS))
+ it(`format(${namespace}, ${reference})`, async function () {
+ expect(await this.caip2.$format(namespace, reference)).to.equal(caip2);
+ });
+
+ for (const { namespace, reference, caip2 } of Object.values(CHAINS))
+ it(`parse(${caip2})`, async function () {
+ expect(await this.caip2.$parse(caip2)).to.deep.equal([namespace, reference]);
+ });
+ });
+
+ describe('CAIP-10', function () {
+ const { address: account } = ethers.Wallet.createRandom();
+
+ it(`local(${account})`, async function () {
+ const { caip10 } = await getLocalCAIP(account);
+ expect(await this.caip10.$local(ethers.Typed.address(account))).to.equal(caip10);
+ });
+
+ for (const { account, caip2, caip10 } of Object.values(CHAINS))
+ it(`format(${caip2}, ${account})`, async function () {
+ expect(await this.caip10.$format(ethers.Typed.string(caip2), ethers.Typed.string(account))).to.equal(caip10);
+ });
+
+ for (const { account, caip2, caip10 } of Object.values(CHAINS))
+ it(`parse(${caip10})`, async function () {
+ expect(await this.caip10.$parse(caip10)).to.deep.equal([caip2, account]);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Context.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Context.behavior.js
new file mode 100644
index 000000000..adb140fc1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Context.behavior.js
@@ -0,0 +1,48 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ return { contextHelper: await ethers.deployContract('ContextMockCaller', []) };
+}
+function shouldBehaveLikeRegularContext() {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('msgSender', function () {
+ it('returns the transaction sender when called from an EOA', async function () {
+ await expect(this.context.connect(this.sender).msgSender()).to.emit(this.context, 'Sender').withArgs(this.sender);
+ });
+
+ it('returns the transaction sender when called from another contract', async function () {
+ await expect(this.contextHelper.connect(this.sender).callSender(this.context))
+ .to.emit(this.context, 'Sender')
+ .withArgs(this.contextHelper);
+ });
+ });
+
+ describe('msgData', function () {
+ const args = [42n, 'OpenZeppelin'];
+
+ it('returns the transaction data when called from an EOA', async function () {
+ const callData = this.context.interface.encodeFunctionData('msgData', args);
+
+ await expect(this.context.msgData(...args))
+ .to.emit(this.context, 'Data')
+ .withArgs(callData, ...args);
+ });
+
+ it('returns the transaction sender when from another contract', async function () {
+ const callData = this.context.interface.encodeFunctionData('msgData', args);
+
+ await expect(this.contextHelper.callData(this.context, ...args))
+ .to.emit(this.context, 'Data')
+ .withArgs(callData, ...args);
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeRegularContext,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Context.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Context.test.js
new file mode 100644
index 000000000..b766729e2
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Context.test.js
@@ -0,0 +1,18 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldBehaveLikeRegularContext } = require('./Context.behavior');
+
+async function fixture() {
+ const [sender] = await ethers.getSigners();
+ const context = await ethers.deployContract('ContextMock', []);
+ return { sender, context };
+}
+
+describe('Context', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeRegularContext();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Create2.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Create2.t.sol
new file mode 100644
index 000000000..6cc037a3b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Create2.t.sol
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
+
+contract Create2Test is Test {
+ function testSymbolicComputeAddressSpillage(bytes32 salt, bytes32 bytecodeHash, address deployer) public {
+ address predicted = Create2.computeAddress(salt, bytecodeHash, deployer);
+ bytes32 spillage;
+ assembly ("memory-safe") {
+ spillage := and(predicted, 0xffffffffffffffffffffffff0000000000000000000000000000000000000000)
+ }
+ assertEq(spillage, bytes32(0));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Create2.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Create2.test.js
new file mode 100644
index 000000000..99c47a0e3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Create2.test.js
@@ -0,0 +1,190 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { RevertType } = require('../helpers/enums');
+
+async function fixture() {
+ const [deployer, other] = await ethers.getSigners();
+
+ const factory = await ethers.deployContract('$Create2');
+
+ // Bytecode for deploying a contract that includes a constructor.
+ // We use a vesting wallet, with 3 constructor arguments.
+ const constructorByteCode = await ethers
+ .getContractFactory('VestingWallet')
+ .then(factory => ethers.concat([factory.bytecode, factory.interface.encodeDeploy([other.address, 0n, 0n])]));
+
+ // Bytecode for deploying a contract that has no constructor log.
+ // Here we use the Create2 helper factory.
+ const constructorLessBytecode = await ethers
+ .getContractFactory('$Create2')
+ .then(factory => ethers.concat([factory.bytecode, factory.interface.encodeDeploy([])]));
+
+ const mockFactory = await ethers.getContractFactory('ConstructorMock');
+
+ return { deployer, other, factory, constructorByteCode, constructorLessBytecode, mockFactory };
+}
+
+describe('Create2', function () {
+ const salt = 'salt message';
+ const saltHex = ethers.id(salt);
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('computeAddress', function () {
+ it('computes the correct contract address', async function () {
+ const onChainComputed = await this.factory.$computeAddress(saltHex, ethers.keccak256(this.constructorByteCode));
+ const offChainComputed = ethers.getCreate2Address(
+ this.factory.target,
+ saltHex,
+ ethers.keccak256(this.constructorByteCode),
+ );
+ expect(onChainComputed).to.equal(offChainComputed);
+ });
+
+ it('computes the correct contract address with deployer', async function () {
+ const onChainComputed = await this.factory.$computeAddress(
+ saltHex,
+ ethers.keccak256(this.constructorByteCode),
+ ethers.Typed.address(this.deployer),
+ );
+ const offChainComputed = ethers.getCreate2Address(
+ this.deployer.address,
+ saltHex,
+ ethers.keccak256(this.constructorByteCode),
+ );
+ expect(onChainComputed).to.equal(offChainComputed);
+ });
+ });
+
+ describe('deploy', function () {
+ it('deploys a contract without constructor', async function () {
+ const offChainComputed = ethers.getCreate2Address(
+ this.factory.target,
+ saltHex,
+ ethers.keccak256(this.constructorLessBytecode),
+ );
+
+ await expect(this.factory.$deploy(0n, saltHex, this.constructorLessBytecode))
+ .to.emit(this.factory, 'return$deploy')
+ .withArgs(offChainComputed);
+
+ expect(this.constructorLessBytecode).to.include((await ethers.provider.getCode(offChainComputed)).slice(2));
+ });
+
+ it('deploys a contract with constructor arguments', async function () {
+ const offChainComputed = ethers.getCreate2Address(
+ this.factory.target,
+ saltHex,
+ ethers.keccak256(this.constructorByteCode),
+ );
+
+ await expect(this.factory.$deploy(0n, saltHex, this.constructorByteCode))
+ .to.emit(this.factory, 'return$deploy')
+ .withArgs(offChainComputed);
+
+ const instance = await ethers.getContractAt('VestingWallet', offChainComputed);
+
+ expect(await instance.owner()).to.equal(this.other);
+ });
+
+ it('deploys a contract with funds deposited in the factory', async function () {
+ const value = 10n;
+
+ await this.deployer.sendTransaction({ to: this.factory, value });
+
+ const offChainComputed = ethers.getCreate2Address(
+ this.factory.target,
+ saltHex,
+ ethers.keccak256(this.constructorByteCode),
+ );
+
+ expect(await ethers.provider.getBalance(this.factory)).to.equal(value);
+ expect(await ethers.provider.getBalance(offChainComputed)).to.equal(0n);
+
+ await expect(this.factory.$deploy(value, saltHex, this.constructorByteCode))
+ .to.emit(this.factory, 'return$deploy')
+ .withArgs(offChainComputed);
+
+ expect(await ethers.provider.getBalance(this.factory)).to.equal(0n);
+ expect(await ethers.provider.getBalance(offChainComputed)).to.equal(value);
+ });
+
+ it('fails deploying a contract in an existent address', async function () {
+ await expect(this.factory.$deploy(0n, saltHex, this.constructorByteCode)).to.emit(this.factory, 'return$deploy');
+
+ await expect(this.factory.$deploy(0n, saltHex, this.constructorByteCode)).to.be.revertedWithCustomError(
+ this.factory,
+ 'FailedDeployment',
+ );
+ });
+
+ it('fails deploying a contract if the bytecode length is zero', async function () {
+ await expect(this.factory.$deploy(0n, saltHex, '0x')).to.be.revertedWithCustomError(
+ this.factory,
+ 'Create2EmptyBytecode',
+ );
+ });
+
+ it('fails deploying a contract if factory contract does not have sufficient balance', async function () {
+ await expect(this.factory.$deploy(1n, saltHex, this.constructorByteCode))
+ .to.be.revertedWithCustomError(this.factory, 'InsufficientBalance')
+ .withArgs(0n, 1n);
+ });
+
+ describe('reverts error thrown during contract creation', function () {
+ it('bubbles up without message', async function () {
+ await expect(
+ this.factory.$deploy(
+ 0n,
+ saltHex,
+ ethers.concat([
+ this.mockFactory.bytecode,
+ this.mockFactory.interface.encodeDeploy([RevertType.RevertWithoutMessage]),
+ ]),
+ ),
+ ).to.be.revertedWithCustomError(this.factory, 'FailedDeployment');
+ });
+
+ it('bubbles up message', async function () {
+ await expect(
+ this.factory.$deploy(
+ 0n,
+ saltHex,
+ ethers.concat([
+ this.mockFactory.bytecode,
+ this.mockFactory.interface.encodeDeploy([RevertType.RevertWithMessage]),
+ ]),
+ ),
+ ).to.be.revertedWith('ConstructorMock: reverting');
+ });
+
+ it('bubbles up custom error', async function () {
+ await expect(
+ this.factory.$deploy(
+ 0n,
+ saltHex,
+ ethers.concat([
+ this.mockFactory.bytecode,
+ this.mockFactory.interface.encodeDeploy([RevertType.RevertWithCustomError]),
+ ]),
+ ),
+ ).to.be.revertedWithCustomError({ interface: this.mockFactory.interface }, 'CustomError');
+ });
+
+ it('bubbles up panic', async function () {
+ await expect(
+ this.factory.$deploy(
+ 0n,
+ saltHex,
+ ethers.concat([this.mockFactory.bytecode, this.mockFactory.interface.encodeDeploy([RevertType.Panic])]),
+ ),
+ ).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Multicall.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Multicall.test.js
new file mode 100644
index 000000000..9c84e443a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Multicall.test.js
@@ -0,0 +1,72 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [holder, alice, bruce] = await ethers.getSigners();
+
+ const amount = 12_000n;
+ const helper = await ethers.deployContract('MulticallHelper');
+ const mock = await ethers.deployContract('$ERC20MulticallMock', ['name', 'symbol']);
+ await mock.$_mint(holder, amount);
+
+ return { holder, alice, bruce, amount, mock, helper };
+}
+
+describe('Multicall', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('batches function calls', async function () {
+ expect(await this.mock.balanceOf(this.alice)).to.equal(0n);
+ expect(await this.mock.balanceOf(this.bruce)).to.equal(0n);
+
+ await expect(
+ this.mock.multicall([
+ this.mock.interface.encodeFunctionData('transfer', [this.alice.address, this.amount / 2n]),
+ this.mock.interface.encodeFunctionData('transfer', [this.bruce.address, this.amount / 3n]),
+ ]),
+ )
+ .to.emit(this.mock, 'Transfer')
+ .withArgs(this.holder, this.alice, this.amount / 2n)
+ .to.emit(this.mock, 'Transfer')
+ .withArgs(this.holder, this.bruce, this.amount / 3n);
+
+ expect(await this.mock.balanceOf(this.alice)).to.equal(this.amount / 2n);
+ expect(await this.mock.balanceOf(this.bruce)).to.equal(this.amount / 3n);
+ });
+
+ it('returns an array with the result of each call', async function () {
+ await this.mock.transfer(this.helper, this.amount);
+ expect(await this.mock.balanceOf(this.helper)).to.equal(this.amount);
+
+ await this.helper.checkReturnValues(this.mock, [this.alice, this.bruce], [this.amount / 2n, this.amount / 3n]);
+ });
+
+ it('reverts previous calls', async function () {
+ expect(await this.mock.balanceOf(this.alice)).to.equal(0n);
+
+ await expect(
+ this.mock.multicall([
+ this.mock.interface.encodeFunctionData('transfer', [this.alice.address, this.amount]),
+ this.mock.interface.encodeFunctionData('transfer', [this.bruce.address, this.amount]),
+ ]),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, 0, this.amount);
+
+ expect(await this.mock.balanceOf(this.alice)).to.equal(0n);
+ });
+
+ it('bubbles up revert reasons', async function () {
+ await expect(
+ this.mock.multicall([
+ this.mock.interface.encodeFunctionData('transfer', [this.alice.address, this.amount]),
+ this.mock.interface.encodeFunctionData('transfer', [this.bruce.address, this.amount]),
+ ]),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'ERC20InsufficientBalance')
+ .withArgs(this.holder, 0, this.amount);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Nonces.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Nonces.behavior.js
new file mode 100644
index 000000000..32201f690
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Nonces.behavior.js
@@ -0,0 +1,189 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+function shouldBehaveLikeNonces() {
+ describe('should behave like Nonces', function () {
+ const sender = ethers.Wallet.createRandom();
+ const other = ethers.Wallet.createRandom();
+
+ it('gets a nonce', async function () {
+ expect(this.mock.nonces(sender)).to.eventually.equal(0n);
+ });
+
+ describe('_useNonce', function () {
+ it('increments a nonce', async function () {
+ expect(this.mock.nonces(sender)).to.eventually.equal(0n);
+
+ const eventName = ['return$_useNonce', 'return$_useNonce_address'].find(name =>
+ this.mock.interface.getEvent(name),
+ );
+
+ await expect(this.mock.$_useNonce(sender)).to.emit(this.mock, eventName).withArgs(0n);
+
+ expect(this.mock.nonces(sender)).to.eventually.equal(1n);
+ });
+
+ it("increments only sender's nonce", async function () {
+ expect(this.mock.nonces(sender)).to.eventually.equal(0n);
+ expect(this.mock.nonces(other)).to.eventually.equal(0n);
+
+ await this.mock.$_useNonce(sender);
+
+ expect(this.mock.nonces(sender)).to.eventually.equal(1n);
+ expect(this.mock.nonces(other)).to.eventually.equal(0n);
+ });
+ });
+
+ describe('_useCheckedNonce', function () {
+ it('increments a nonce', async function () {
+ // current nonce is 0n
+ expect(this.mock.nonces(sender)).to.eventually.equal(0n);
+
+ await this.mock.$_useCheckedNonce(sender, 0n);
+
+ expect(this.mock.nonces(sender)).to.eventually.equal(1n);
+ });
+
+ it("increments only sender's nonce", async function () {
+ // current nonce is 0n
+ expect(this.mock.nonces(sender)).to.eventually.equal(0n);
+ expect(this.mock.nonces(other)).to.eventually.equal(0n);
+
+ await this.mock.$_useCheckedNonce(sender, 0n);
+
+ expect(this.mock.nonces(sender)).to.eventually.equal(1n);
+ expect(this.mock.nonces(other)).to.eventually.equal(0n);
+ });
+
+ it('reverts when nonce is not the expected', async function () {
+ const currentNonce = await this.mock.nonces(sender);
+
+ await expect(this.mock.$_useCheckedNonce(sender, currentNonce + 1n))
+ .to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
+ .withArgs(sender, currentNonce);
+ });
+ });
+ });
+}
+
+function shouldBehaveLikeNoncesKeyed() {
+ describe('should support nonces with keys', function () {
+ const sender = ethers.Wallet.createRandom();
+
+ const keyOffset = key => key << 64n;
+
+ it('gets a nonce', async function () {
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n);
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n);
+ });
+
+ describe('_useNonce', function () {
+ it('default variant uses key 0', async function () {
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n);
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n);
+
+ await expect(this.mock.$_useNonce(sender)).to.emit(this.mock, 'return$_useNonce_address').withArgs(0n);
+
+ await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(0n)))
+ .to.emit(this.mock, 'return$_useNonce_address_uint192')
+ .withArgs(keyOffset(0n) + 1n);
+
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 2n);
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n);
+ });
+
+ it('use nonce at another key', async function () {
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n);
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 0n);
+
+ await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(17n)))
+ .to.emit(this.mock, 'return$_useNonce_address_uint192')
+ .withArgs(keyOffset(17n) + 0n);
+
+ await expect(this.mock.$_useNonce(sender, ethers.Typed.uint192(17n)))
+ .to.emit(this.mock, 'return$_useNonce_address_uint192')
+ .withArgs(keyOffset(17n) + 1n);
+
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(keyOffset(0n) + 0n);
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(keyOffset(17n) + 2n);
+ });
+ });
+
+ describe('_useCheckedNonce(address, uint256)', function () {
+ it('default variant uses key 0', async function () {
+ const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(0n));
+
+ await this.mock.$_useCheckedNonce(sender, currentNonce);
+
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n);
+ });
+
+ it('use nonce at another key', async function () {
+ const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(17n));
+
+ await this.mock.$_useCheckedNonce(sender, currentNonce);
+
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n);
+ });
+
+ it('reverts when nonce is not the expected', async function () {
+ const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(42n));
+
+ // use and increment
+ await this.mock.$_useCheckedNonce(sender, currentNonce);
+
+ // reuse same nonce
+ await expect(this.mock.$_useCheckedNonce(sender, currentNonce))
+ .to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
+ .withArgs(sender, currentNonce + 1n);
+
+ // use "future" nonce too early
+ await expect(this.mock.$_useCheckedNonce(sender, currentNonce + 10n))
+ .to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
+ .withArgs(sender, currentNonce + 1n);
+ });
+ });
+
+ describe('_useCheckedNonce(address, uint192, uint64)', function () {
+ const MASK = 0xffffffffffffffffn;
+
+ it('default variant uses key 0', async function () {
+ const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(0n));
+
+ await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(0n), currentNonce);
+
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(0n))).to.eventually.equal(currentNonce + 1n);
+ });
+
+ it('use nonce at another key', async function () {
+ const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(17n));
+
+ await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(17n), currentNonce & MASK);
+
+ expect(this.mock.nonces(sender, ethers.Typed.uint192(17n))).to.eventually.equal(currentNonce + 1n);
+ });
+
+ it('reverts when nonce is not the expected', async function () {
+ const currentNonce = await this.mock.nonces(sender, ethers.Typed.uint192(42n));
+
+ // use and increment
+ await this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(42n), currentNonce & MASK);
+
+ // reuse same nonce
+ await expect(this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(42n), currentNonce & MASK))
+ .to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
+ .withArgs(sender, currentNonce + 1n);
+
+ // use "future" nonce too early
+ await expect(this.mock.$_useCheckedNonce(sender, ethers.Typed.uint192(42n), (currentNonce & MASK) + 10n))
+ .to.be.revertedWithCustomError(this.mock, 'InvalidAccountNonce')
+ .withArgs(sender, currentNonce + 1n);
+ });
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeNonces,
+ shouldBehaveLikeNoncesKeyed,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Nonces.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Nonces.test.js
new file mode 100644
index 000000000..85aa7358a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Nonces.test.js
@@ -0,0 +1,16 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { shouldBehaveLikeNonces } = require('./Nonces.behavior');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Nonces');
+ return { mock };
+}
+
+describe('Nonces', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeNonces();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/NoncesKeyed.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/NoncesKeyed.test.js
new file mode 100644
index 000000000..c46948ee4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/NoncesKeyed.test.js
@@ -0,0 +1,17 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { shouldBehaveLikeNonces, shouldBehaveLikeNoncesKeyed } = require('./Nonces.behavior');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$NoncesKeyed');
+ return { mock };
+}
+
+describe('NoncesKeyed', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldBehaveLikeNonces();
+ shouldBehaveLikeNoncesKeyed();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Packing.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Packing.t.sol
new file mode 100644
index 000000000..40f052c80
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Packing.t.sol
@@ -0,0 +1,993 @@
+// SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/Packing.t.js.
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Packing} from "@openzeppelin/contracts/utils/Packing.sol";
+
+contract PackingTest is Test {
+ using Packing for *;
+
+ function testPack(bytes1 left, bytes1 right) external pure {
+ assertEq(left, Packing.pack_1_1(left, right).extract_2_1(0));
+ assertEq(right, Packing.pack_1_1(left, right).extract_2_1(1));
+ }
+
+ function testPack(bytes2 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_2_2(left, right).extract_4_2(0));
+ assertEq(right, Packing.pack_2_2(left, right).extract_4_2(2));
+ }
+
+ function testPack(bytes2 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_2_4(left, right).extract_6_2(0));
+ assertEq(right, Packing.pack_2_4(left, right).extract_6_4(2));
+ }
+
+ function testPack(bytes2 left, bytes6 right) external pure {
+ assertEq(left, Packing.pack_2_6(left, right).extract_8_2(0));
+ assertEq(right, Packing.pack_2_6(left, right).extract_8_6(2));
+ }
+
+ function testPack(bytes2 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_2_8(left, right).extract_10_2(0));
+ assertEq(right, Packing.pack_2_8(left, right).extract_10_8(2));
+ }
+
+ function testPack(bytes2 left, bytes10 right) external pure {
+ assertEq(left, Packing.pack_2_10(left, right).extract_12_2(0));
+ assertEq(right, Packing.pack_2_10(left, right).extract_12_10(2));
+ }
+
+ function testPack(bytes2 left, bytes20 right) external pure {
+ assertEq(left, Packing.pack_2_20(left, right).extract_22_2(0));
+ assertEq(right, Packing.pack_2_20(left, right).extract_22_20(2));
+ }
+
+ function testPack(bytes2 left, bytes22 right) external pure {
+ assertEq(left, Packing.pack_2_22(left, right).extract_24_2(0));
+ assertEq(right, Packing.pack_2_22(left, right).extract_24_22(2));
+ }
+
+ function testPack(bytes4 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_4_2(left, right).extract_6_4(0));
+ assertEq(right, Packing.pack_4_2(left, right).extract_6_2(4));
+ }
+
+ function testPack(bytes4 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_4_4(left, right).extract_8_4(0));
+ assertEq(right, Packing.pack_4_4(left, right).extract_8_4(4));
+ }
+
+ function testPack(bytes4 left, bytes6 right) external pure {
+ assertEq(left, Packing.pack_4_6(left, right).extract_10_4(0));
+ assertEq(right, Packing.pack_4_6(left, right).extract_10_6(4));
+ }
+
+ function testPack(bytes4 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_4_8(left, right).extract_12_4(0));
+ assertEq(right, Packing.pack_4_8(left, right).extract_12_8(4));
+ }
+
+ function testPack(bytes4 left, bytes12 right) external pure {
+ assertEq(left, Packing.pack_4_12(left, right).extract_16_4(0));
+ assertEq(right, Packing.pack_4_12(left, right).extract_16_12(4));
+ }
+
+ function testPack(bytes4 left, bytes16 right) external pure {
+ assertEq(left, Packing.pack_4_16(left, right).extract_20_4(0));
+ assertEq(right, Packing.pack_4_16(left, right).extract_20_16(4));
+ }
+
+ function testPack(bytes4 left, bytes20 right) external pure {
+ assertEq(left, Packing.pack_4_20(left, right).extract_24_4(0));
+ assertEq(right, Packing.pack_4_20(left, right).extract_24_20(4));
+ }
+
+ function testPack(bytes4 left, bytes24 right) external pure {
+ assertEq(left, Packing.pack_4_24(left, right).extract_28_4(0));
+ assertEq(right, Packing.pack_4_24(left, right).extract_28_24(4));
+ }
+
+ function testPack(bytes4 left, bytes28 right) external pure {
+ assertEq(left, Packing.pack_4_28(left, right).extract_32_4(0));
+ assertEq(right, Packing.pack_4_28(left, right).extract_32_28(4));
+ }
+
+ function testPack(bytes6 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_6_2(left, right).extract_8_6(0));
+ assertEq(right, Packing.pack_6_2(left, right).extract_8_2(6));
+ }
+
+ function testPack(bytes6 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_6_4(left, right).extract_10_6(0));
+ assertEq(right, Packing.pack_6_4(left, right).extract_10_4(6));
+ }
+
+ function testPack(bytes6 left, bytes6 right) external pure {
+ assertEq(left, Packing.pack_6_6(left, right).extract_12_6(0));
+ assertEq(right, Packing.pack_6_6(left, right).extract_12_6(6));
+ }
+
+ function testPack(bytes6 left, bytes10 right) external pure {
+ assertEq(left, Packing.pack_6_10(left, right).extract_16_6(0));
+ assertEq(right, Packing.pack_6_10(left, right).extract_16_10(6));
+ }
+
+ function testPack(bytes6 left, bytes16 right) external pure {
+ assertEq(left, Packing.pack_6_16(left, right).extract_22_6(0));
+ assertEq(right, Packing.pack_6_16(left, right).extract_22_16(6));
+ }
+
+ function testPack(bytes6 left, bytes22 right) external pure {
+ assertEq(left, Packing.pack_6_22(left, right).extract_28_6(0));
+ assertEq(right, Packing.pack_6_22(left, right).extract_28_22(6));
+ }
+
+ function testPack(bytes8 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_8_2(left, right).extract_10_8(0));
+ assertEq(right, Packing.pack_8_2(left, right).extract_10_2(8));
+ }
+
+ function testPack(bytes8 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_8_4(left, right).extract_12_8(0));
+ assertEq(right, Packing.pack_8_4(left, right).extract_12_4(8));
+ }
+
+ function testPack(bytes8 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_8_8(left, right).extract_16_8(0));
+ assertEq(right, Packing.pack_8_8(left, right).extract_16_8(8));
+ }
+
+ function testPack(bytes8 left, bytes12 right) external pure {
+ assertEq(left, Packing.pack_8_12(left, right).extract_20_8(0));
+ assertEq(right, Packing.pack_8_12(left, right).extract_20_12(8));
+ }
+
+ function testPack(bytes8 left, bytes16 right) external pure {
+ assertEq(left, Packing.pack_8_16(left, right).extract_24_8(0));
+ assertEq(right, Packing.pack_8_16(left, right).extract_24_16(8));
+ }
+
+ function testPack(bytes8 left, bytes20 right) external pure {
+ assertEq(left, Packing.pack_8_20(left, right).extract_28_8(0));
+ assertEq(right, Packing.pack_8_20(left, right).extract_28_20(8));
+ }
+
+ function testPack(bytes8 left, bytes24 right) external pure {
+ assertEq(left, Packing.pack_8_24(left, right).extract_32_8(0));
+ assertEq(right, Packing.pack_8_24(left, right).extract_32_24(8));
+ }
+
+ function testPack(bytes10 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_10_2(left, right).extract_12_10(0));
+ assertEq(right, Packing.pack_10_2(left, right).extract_12_2(10));
+ }
+
+ function testPack(bytes10 left, bytes6 right) external pure {
+ assertEq(left, Packing.pack_10_6(left, right).extract_16_10(0));
+ assertEq(right, Packing.pack_10_6(left, right).extract_16_6(10));
+ }
+
+ function testPack(bytes10 left, bytes10 right) external pure {
+ assertEq(left, Packing.pack_10_10(left, right).extract_20_10(0));
+ assertEq(right, Packing.pack_10_10(left, right).extract_20_10(10));
+ }
+
+ function testPack(bytes10 left, bytes12 right) external pure {
+ assertEq(left, Packing.pack_10_12(left, right).extract_22_10(0));
+ assertEq(right, Packing.pack_10_12(left, right).extract_22_12(10));
+ }
+
+ function testPack(bytes10 left, bytes22 right) external pure {
+ assertEq(left, Packing.pack_10_22(left, right).extract_32_10(0));
+ assertEq(right, Packing.pack_10_22(left, right).extract_32_22(10));
+ }
+
+ function testPack(bytes12 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_12_4(left, right).extract_16_12(0));
+ assertEq(right, Packing.pack_12_4(left, right).extract_16_4(12));
+ }
+
+ function testPack(bytes12 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_12_8(left, right).extract_20_12(0));
+ assertEq(right, Packing.pack_12_8(left, right).extract_20_8(12));
+ }
+
+ function testPack(bytes12 left, bytes10 right) external pure {
+ assertEq(left, Packing.pack_12_10(left, right).extract_22_12(0));
+ assertEq(right, Packing.pack_12_10(left, right).extract_22_10(12));
+ }
+
+ function testPack(bytes12 left, bytes12 right) external pure {
+ assertEq(left, Packing.pack_12_12(left, right).extract_24_12(0));
+ assertEq(right, Packing.pack_12_12(left, right).extract_24_12(12));
+ }
+
+ function testPack(bytes12 left, bytes16 right) external pure {
+ assertEq(left, Packing.pack_12_16(left, right).extract_28_12(0));
+ assertEq(right, Packing.pack_12_16(left, right).extract_28_16(12));
+ }
+
+ function testPack(bytes12 left, bytes20 right) external pure {
+ assertEq(left, Packing.pack_12_20(left, right).extract_32_12(0));
+ assertEq(right, Packing.pack_12_20(left, right).extract_32_20(12));
+ }
+
+ function testPack(bytes16 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_16_4(left, right).extract_20_16(0));
+ assertEq(right, Packing.pack_16_4(left, right).extract_20_4(16));
+ }
+
+ function testPack(bytes16 left, bytes6 right) external pure {
+ assertEq(left, Packing.pack_16_6(left, right).extract_22_16(0));
+ assertEq(right, Packing.pack_16_6(left, right).extract_22_6(16));
+ }
+
+ function testPack(bytes16 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_16_8(left, right).extract_24_16(0));
+ assertEq(right, Packing.pack_16_8(left, right).extract_24_8(16));
+ }
+
+ function testPack(bytes16 left, bytes12 right) external pure {
+ assertEq(left, Packing.pack_16_12(left, right).extract_28_16(0));
+ assertEq(right, Packing.pack_16_12(left, right).extract_28_12(16));
+ }
+
+ function testPack(bytes16 left, bytes16 right) external pure {
+ assertEq(left, Packing.pack_16_16(left, right).extract_32_16(0));
+ assertEq(right, Packing.pack_16_16(left, right).extract_32_16(16));
+ }
+
+ function testPack(bytes20 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_20_2(left, right).extract_22_20(0));
+ assertEq(right, Packing.pack_20_2(left, right).extract_22_2(20));
+ }
+
+ function testPack(bytes20 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_20_4(left, right).extract_24_20(0));
+ assertEq(right, Packing.pack_20_4(left, right).extract_24_4(20));
+ }
+
+ function testPack(bytes20 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_20_8(left, right).extract_28_20(0));
+ assertEq(right, Packing.pack_20_8(left, right).extract_28_8(20));
+ }
+
+ function testPack(bytes20 left, bytes12 right) external pure {
+ assertEq(left, Packing.pack_20_12(left, right).extract_32_20(0));
+ assertEq(right, Packing.pack_20_12(left, right).extract_32_12(20));
+ }
+
+ function testPack(bytes22 left, bytes2 right) external pure {
+ assertEq(left, Packing.pack_22_2(left, right).extract_24_22(0));
+ assertEq(right, Packing.pack_22_2(left, right).extract_24_2(22));
+ }
+
+ function testPack(bytes22 left, bytes6 right) external pure {
+ assertEq(left, Packing.pack_22_6(left, right).extract_28_22(0));
+ assertEq(right, Packing.pack_22_6(left, right).extract_28_6(22));
+ }
+
+ function testPack(bytes22 left, bytes10 right) external pure {
+ assertEq(left, Packing.pack_22_10(left, right).extract_32_22(0));
+ assertEq(right, Packing.pack_22_10(left, right).extract_32_10(22));
+ }
+
+ function testPack(bytes24 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_24_4(left, right).extract_28_24(0));
+ assertEq(right, Packing.pack_24_4(left, right).extract_28_4(24));
+ }
+
+ function testPack(bytes24 left, bytes8 right) external pure {
+ assertEq(left, Packing.pack_24_8(left, right).extract_32_24(0));
+ assertEq(right, Packing.pack_24_8(left, right).extract_32_8(24));
+ }
+
+ function testPack(bytes28 left, bytes4 right) external pure {
+ assertEq(left, Packing.pack_28_4(left, right).extract_32_28(0));
+ assertEq(right, Packing.pack_28_4(left, right).extract_32_4(28));
+ }
+
+ function testReplace(bytes2 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 1));
+
+ bytes1 oldValue = container.extract_2_1(offset);
+
+ assertEq(newValue, container.replace_2_1(newValue, offset).extract_2_1(offset));
+ assertEq(container, container.replace_2_1(newValue, offset).replace_2_1(oldValue, offset));
+ }
+
+ function testReplace(bytes4 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 3));
+
+ bytes1 oldValue = container.extract_4_1(offset);
+
+ assertEq(newValue, container.replace_4_1(newValue, offset).extract_4_1(offset));
+ assertEq(container, container.replace_4_1(newValue, offset).replace_4_1(oldValue, offset));
+ }
+
+ function testReplace(bytes4 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes2 oldValue = container.extract_4_2(offset);
+
+ assertEq(newValue, container.replace_4_2(newValue, offset).extract_4_2(offset));
+ assertEq(container, container.replace_4_2(newValue, offset).replace_4_2(oldValue, offset));
+ }
+
+ function testReplace(bytes6 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 5));
+
+ bytes1 oldValue = container.extract_6_1(offset);
+
+ assertEq(newValue, container.replace_6_1(newValue, offset).extract_6_1(offset));
+ assertEq(container, container.replace_6_1(newValue, offset).replace_6_1(oldValue, offset));
+ }
+
+ function testReplace(bytes6 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes2 oldValue = container.extract_6_2(offset);
+
+ assertEq(newValue, container.replace_6_2(newValue, offset).extract_6_2(offset));
+ assertEq(container, container.replace_6_2(newValue, offset).replace_6_2(oldValue, offset));
+ }
+
+ function testReplace(bytes6 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes4 oldValue = container.extract_6_4(offset);
+
+ assertEq(newValue, container.replace_6_4(newValue, offset).extract_6_4(offset));
+ assertEq(container, container.replace_6_4(newValue, offset).replace_6_4(oldValue, offset));
+ }
+
+ function testReplace(bytes8 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 7));
+
+ bytes1 oldValue = container.extract_8_1(offset);
+
+ assertEq(newValue, container.replace_8_1(newValue, offset).extract_8_1(offset));
+ assertEq(container, container.replace_8_1(newValue, offset).replace_8_1(oldValue, offset));
+ }
+
+ function testReplace(bytes8 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 6));
+
+ bytes2 oldValue = container.extract_8_2(offset);
+
+ assertEq(newValue, container.replace_8_2(newValue, offset).extract_8_2(offset));
+ assertEq(container, container.replace_8_2(newValue, offset).replace_8_2(oldValue, offset));
+ }
+
+ function testReplace(bytes8 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes4 oldValue = container.extract_8_4(offset);
+
+ assertEq(newValue, container.replace_8_4(newValue, offset).extract_8_4(offset));
+ assertEq(container, container.replace_8_4(newValue, offset).replace_8_4(oldValue, offset));
+ }
+
+ function testReplace(bytes8 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes6 oldValue = container.extract_8_6(offset);
+
+ assertEq(newValue, container.replace_8_6(newValue, offset).extract_8_6(offset));
+ assertEq(container, container.replace_8_6(newValue, offset).replace_8_6(oldValue, offset));
+ }
+
+ function testReplace(bytes10 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 9));
+
+ bytes1 oldValue = container.extract_10_1(offset);
+
+ assertEq(newValue, container.replace_10_1(newValue, offset).extract_10_1(offset));
+ assertEq(container, container.replace_10_1(newValue, offset).replace_10_1(oldValue, offset));
+ }
+
+ function testReplace(bytes10 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes2 oldValue = container.extract_10_2(offset);
+
+ assertEq(newValue, container.replace_10_2(newValue, offset).extract_10_2(offset));
+ assertEq(container, container.replace_10_2(newValue, offset).replace_10_2(oldValue, offset));
+ }
+
+ function testReplace(bytes10 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 6));
+
+ bytes4 oldValue = container.extract_10_4(offset);
+
+ assertEq(newValue, container.replace_10_4(newValue, offset).extract_10_4(offset));
+ assertEq(container, container.replace_10_4(newValue, offset).replace_10_4(oldValue, offset));
+ }
+
+ function testReplace(bytes10 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes6 oldValue = container.extract_10_6(offset);
+
+ assertEq(newValue, container.replace_10_6(newValue, offset).extract_10_6(offset));
+ assertEq(container, container.replace_10_6(newValue, offset).replace_10_6(oldValue, offset));
+ }
+
+ function testReplace(bytes10 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes8 oldValue = container.extract_10_8(offset);
+
+ assertEq(newValue, container.replace_10_8(newValue, offset).extract_10_8(offset));
+ assertEq(container, container.replace_10_8(newValue, offset).replace_10_8(oldValue, offset));
+ }
+
+ function testReplace(bytes12 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 11));
+
+ bytes1 oldValue = container.extract_12_1(offset);
+
+ assertEq(newValue, container.replace_12_1(newValue, offset).extract_12_1(offset));
+ assertEq(container, container.replace_12_1(newValue, offset).replace_12_1(oldValue, offset));
+ }
+
+ function testReplace(bytes12 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 10));
+
+ bytes2 oldValue = container.extract_12_2(offset);
+
+ assertEq(newValue, container.replace_12_2(newValue, offset).extract_12_2(offset));
+ assertEq(container, container.replace_12_2(newValue, offset).replace_12_2(oldValue, offset));
+ }
+
+ function testReplace(bytes12 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes4 oldValue = container.extract_12_4(offset);
+
+ assertEq(newValue, container.replace_12_4(newValue, offset).extract_12_4(offset));
+ assertEq(container, container.replace_12_4(newValue, offset).replace_12_4(oldValue, offset));
+ }
+
+ function testReplace(bytes12 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 6));
+
+ bytes6 oldValue = container.extract_12_6(offset);
+
+ assertEq(newValue, container.replace_12_6(newValue, offset).extract_12_6(offset));
+ assertEq(container, container.replace_12_6(newValue, offset).replace_12_6(oldValue, offset));
+ }
+
+ function testReplace(bytes12 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes8 oldValue = container.extract_12_8(offset);
+
+ assertEq(newValue, container.replace_12_8(newValue, offset).extract_12_8(offset));
+ assertEq(container, container.replace_12_8(newValue, offset).replace_12_8(oldValue, offset));
+ }
+
+ function testReplace(bytes12 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes10 oldValue = container.extract_12_10(offset);
+
+ assertEq(newValue, container.replace_12_10(newValue, offset).extract_12_10(offset));
+ assertEq(container, container.replace_12_10(newValue, offset).replace_12_10(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 15));
+
+ bytes1 oldValue = container.extract_16_1(offset);
+
+ assertEq(newValue, container.replace_16_1(newValue, offset).extract_16_1(offset));
+ assertEq(container, container.replace_16_1(newValue, offset).replace_16_1(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 14));
+
+ bytes2 oldValue = container.extract_16_2(offset);
+
+ assertEq(newValue, container.replace_16_2(newValue, offset).extract_16_2(offset));
+ assertEq(container, container.replace_16_2(newValue, offset).replace_16_2(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 12));
+
+ bytes4 oldValue = container.extract_16_4(offset);
+
+ assertEq(newValue, container.replace_16_4(newValue, offset).extract_16_4(offset));
+ assertEq(container, container.replace_16_4(newValue, offset).replace_16_4(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 10));
+
+ bytes6 oldValue = container.extract_16_6(offset);
+
+ assertEq(newValue, container.replace_16_6(newValue, offset).extract_16_6(offset));
+ assertEq(container, container.replace_16_6(newValue, offset).replace_16_6(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes8 oldValue = container.extract_16_8(offset);
+
+ assertEq(newValue, container.replace_16_8(newValue, offset).extract_16_8(offset));
+ assertEq(container, container.replace_16_8(newValue, offset).replace_16_8(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 6));
+
+ bytes10 oldValue = container.extract_16_10(offset);
+
+ assertEq(newValue, container.replace_16_10(newValue, offset).extract_16_10(offset));
+ assertEq(container, container.replace_16_10(newValue, offset).replace_16_10(oldValue, offset));
+ }
+
+ function testReplace(bytes16 container, bytes12 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes12 oldValue = container.extract_16_12(offset);
+
+ assertEq(newValue, container.replace_16_12(newValue, offset).extract_16_12(offset));
+ assertEq(container, container.replace_16_12(newValue, offset).replace_16_12(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 19));
+
+ bytes1 oldValue = container.extract_20_1(offset);
+
+ assertEq(newValue, container.replace_20_1(newValue, offset).extract_20_1(offset));
+ assertEq(container, container.replace_20_1(newValue, offset).replace_20_1(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 18));
+
+ bytes2 oldValue = container.extract_20_2(offset);
+
+ assertEq(newValue, container.replace_20_2(newValue, offset).extract_20_2(offset));
+ assertEq(container, container.replace_20_2(newValue, offset).replace_20_2(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 16));
+
+ bytes4 oldValue = container.extract_20_4(offset);
+
+ assertEq(newValue, container.replace_20_4(newValue, offset).extract_20_4(offset));
+ assertEq(container, container.replace_20_4(newValue, offset).replace_20_4(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 14));
+
+ bytes6 oldValue = container.extract_20_6(offset);
+
+ assertEq(newValue, container.replace_20_6(newValue, offset).extract_20_6(offset));
+ assertEq(container, container.replace_20_6(newValue, offset).replace_20_6(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 12));
+
+ bytes8 oldValue = container.extract_20_8(offset);
+
+ assertEq(newValue, container.replace_20_8(newValue, offset).extract_20_8(offset));
+ assertEq(container, container.replace_20_8(newValue, offset).replace_20_8(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 10));
+
+ bytes10 oldValue = container.extract_20_10(offset);
+
+ assertEq(newValue, container.replace_20_10(newValue, offset).extract_20_10(offset));
+ assertEq(container, container.replace_20_10(newValue, offset).replace_20_10(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes12 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes12 oldValue = container.extract_20_12(offset);
+
+ assertEq(newValue, container.replace_20_12(newValue, offset).extract_20_12(offset));
+ assertEq(container, container.replace_20_12(newValue, offset).replace_20_12(oldValue, offset));
+ }
+
+ function testReplace(bytes20 container, bytes16 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes16 oldValue = container.extract_20_16(offset);
+
+ assertEq(newValue, container.replace_20_16(newValue, offset).extract_20_16(offset));
+ assertEq(container, container.replace_20_16(newValue, offset).replace_20_16(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 21));
+
+ bytes1 oldValue = container.extract_22_1(offset);
+
+ assertEq(newValue, container.replace_22_1(newValue, offset).extract_22_1(offset));
+ assertEq(container, container.replace_22_1(newValue, offset).replace_22_1(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 20));
+
+ bytes2 oldValue = container.extract_22_2(offset);
+
+ assertEq(newValue, container.replace_22_2(newValue, offset).extract_22_2(offset));
+ assertEq(container, container.replace_22_2(newValue, offset).replace_22_2(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 18));
+
+ bytes4 oldValue = container.extract_22_4(offset);
+
+ assertEq(newValue, container.replace_22_4(newValue, offset).extract_22_4(offset));
+ assertEq(container, container.replace_22_4(newValue, offset).replace_22_4(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 16));
+
+ bytes6 oldValue = container.extract_22_6(offset);
+
+ assertEq(newValue, container.replace_22_6(newValue, offset).extract_22_6(offset));
+ assertEq(container, container.replace_22_6(newValue, offset).replace_22_6(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 14));
+
+ bytes8 oldValue = container.extract_22_8(offset);
+
+ assertEq(newValue, container.replace_22_8(newValue, offset).extract_22_8(offset));
+ assertEq(container, container.replace_22_8(newValue, offset).replace_22_8(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 12));
+
+ bytes10 oldValue = container.extract_22_10(offset);
+
+ assertEq(newValue, container.replace_22_10(newValue, offset).extract_22_10(offset));
+ assertEq(container, container.replace_22_10(newValue, offset).replace_22_10(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes12 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 10));
+
+ bytes12 oldValue = container.extract_22_12(offset);
+
+ assertEq(newValue, container.replace_22_12(newValue, offset).extract_22_12(offset));
+ assertEq(container, container.replace_22_12(newValue, offset).replace_22_12(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes16 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 6));
+
+ bytes16 oldValue = container.extract_22_16(offset);
+
+ assertEq(newValue, container.replace_22_16(newValue, offset).extract_22_16(offset));
+ assertEq(container, container.replace_22_16(newValue, offset).replace_22_16(oldValue, offset));
+ }
+
+ function testReplace(bytes22 container, bytes20 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes20 oldValue = container.extract_22_20(offset);
+
+ assertEq(newValue, container.replace_22_20(newValue, offset).extract_22_20(offset));
+ assertEq(container, container.replace_22_20(newValue, offset).replace_22_20(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 23));
+
+ bytes1 oldValue = container.extract_24_1(offset);
+
+ assertEq(newValue, container.replace_24_1(newValue, offset).extract_24_1(offset));
+ assertEq(container, container.replace_24_1(newValue, offset).replace_24_1(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 22));
+
+ bytes2 oldValue = container.extract_24_2(offset);
+
+ assertEq(newValue, container.replace_24_2(newValue, offset).extract_24_2(offset));
+ assertEq(container, container.replace_24_2(newValue, offset).replace_24_2(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 20));
+
+ bytes4 oldValue = container.extract_24_4(offset);
+
+ assertEq(newValue, container.replace_24_4(newValue, offset).extract_24_4(offset));
+ assertEq(container, container.replace_24_4(newValue, offset).replace_24_4(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 18));
+
+ bytes6 oldValue = container.extract_24_6(offset);
+
+ assertEq(newValue, container.replace_24_6(newValue, offset).extract_24_6(offset));
+ assertEq(container, container.replace_24_6(newValue, offset).replace_24_6(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 16));
+
+ bytes8 oldValue = container.extract_24_8(offset);
+
+ assertEq(newValue, container.replace_24_8(newValue, offset).extract_24_8(offset));
+ assertEq(container, container.replace_24_8(newValue, offset).replace_24_8(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 14));
+
+ bytes10 oldValue = container.extract_24_10(offset);
+
+ assertEq(newValue, container.replace_24_10(newValue, offset).extract_24_10(offset));
+ assertEq(container, container.replace_24_10(newValue, offset).replace_24_10(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes12 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 12));
+
+ bytes12 oldValue = container.extract_24_12(offset);
+
+ assertEq(newValue, container.replace_24_12(newValue, offset).extract_24_12(offset));
+ assertEq(container, container.replace_24_12(newValue, offset).replace_24_12(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes16 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes16 oldValue = container.extract_24_16(offset);
+
+ assertEq(newValue, container.replace_24_16(newValue, offset).extract_24_16(offset));
+ assertEq(container, container.replace_24_16(newValue, offset).replace_24_16(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes20 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes20 oldValue = container.extract_24_20(offset);
+
+ assertEq(newValue, container.replace_24_20(newValue, offset).extract_24_20(offset));
+ assertEq(container, container.replace_24_20(newValue, offset).replace_24_20(oldValue, offset));
+ }
+
+ function testReplace(bytes24 container, bytes22 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 2));
+
+ bytes22 oldValue = container.extract_24_22(offset);
+
+ assertEq(newValue, container.replace_24_22(newValue, offset).extract_24_22(offset));
+ assertEq(container, container.replace_24_22(newValue, offset).replace_24_22(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 27));
+
+ bytes1 oldValue = container.extract_28_1(offset);
+
+ assertEq(newValue, container.replace_28_1(newValue, offset).extract_28_1(offset));
+ assertEq(container, container.replace_28_1(newValue, offset).replace_28_1(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 26));
+
+ bytes2 oldValue = container.extract_28_2(offset);
+
+ assertEq(newValue, container.replace_28_2(newValue, offset).extract_28_2(offset));
+ assertEq(container, container.replace_28_2(newValue, offset).replace_28_2(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 24));
+
+ bytes4 oldValue = container.extract_28_4(offset);
+
+ assertEq(newValue, container.replace_28_4(newValue, offset).extract_28_4(offset));
+ assertEq(container, container.replace_28_4(newValue, offset).replace_28_4(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 22));
+
+ bytes6 oldValue = container.extract_28_6(offset);
+
+ assertEq(newValue, container.replace_28_6(newValue, offset).extract_28_6(offset));
+ assertEq(container, container.replace_28_6(newValue, offset).replace_28_6(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 20));
+
+ bytes8 oldValue = container.extract_28_8(offset);
+
+ assertEq(newValue, container.replace_28_8(newValue, offset).extract_28_8(offset));
+ assertEq(container, container.replace_28_8(newValue, offset).replace_28_8(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 18));
+
+ bytes10 oldValue = container.extract_28_10(offset);
+
+ assertEq(newValue, container.replace_28_10(newValue, offset).extract_28_10(offset));
+ assertEq(container, container.replace_28_10(newValue, offset).replace_28_10(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes12 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 16));
+
+ bytes12 oldValue = container.extract_28_12(offset);
+
+ assertEq(newValue, container.replace_28_12(newValue, offset).extract_28_12(offset));
+ assertEq(container, container.replace_28_12(newValue, offset).replace_28_12(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes16 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 12));
+
+ bytes16 oldValue = container.extract_28_16(offset);
+
+ assertEq(newValue, container.replace_28_16(newValue, offset).extract_28_16(offset));
+ assertEq(container, container.replace_28_16(newValue, offset).replace_28_16(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes20 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes20 oldValue = container.extract_28_20(offset);
+
+ assertEq(newValue, container.replace_28_20(newValue, offset).extract_28_20(offset));
+ assertEq(container, container.replace_28_20(newValue, offset).replace_28_20(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes22 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 6));
+
+ bytes22 oldValue = container.extract_28_22(offset);
+
+ assertEq(newValue, container.replace_28_22(newValue, offset).extract_28_22(offset));
+ assertEq(container, container.replace_28_22(newValue, offset).replace_28_22(oldValue, offset));
+ }
+
+ function testReplace(bytes28 container, bytes24 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes24 oldValue = container.extract_28_24(offset);
+
+ assertEq(newValue, container.replace_28_24(newValue, offset).extract_28_24(offset));
+ assertEq(container, container.replace_28_24(newValue, offset).replace_28_24(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes1 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 31));
+
+ bytes1 oldValue = container.extract_32_1(offset);
+
+ assertEq(newValue, container.replace_32_1(newValue, offset).extract_32_1(offset));
+ assertEq(container, container.replace_32_1(newValue, offset).replace_32_1(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes2 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 30));
+
+ bytes2 oldValue = container.extract_32_2(offset);
+
+ assertEq(newValue, container.replace_32_2(newValue, offset).extract_32_2(offset));
+ assertEq(container, container.replace_32_2(newValue, offset).replace_32_2(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes4 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 28));
+
+ bytes4 oldValue = container.extract_32_4(offset);
+
+ assertEq(newValue, container.replace_32_4(newValue, offset).extract_32_4(offset));
+ assertEq(container, container.replace_32_4(newValue, offset).replace_32_4(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes6 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 26));
+
+ bytes6 oldValue = container.extract_32_6(offset);
+
+ assertEq(newValue, container.replace_32_6(newValue, offset).extract_32_6(offset));
+ assertEq(container, container.replace_32_6(newValue, offset).replace_32_6(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes8 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 24));
+
+ bytes8 oldValue = container.extract_32_8(offset);
+
+ assertEq(newValue, container.replace_32_8(newValue, offset).extract_32_8(offset));
+ assertEq(container, container.replace_32_8(newValue, offset).replace_32_8(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes10 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 22));
+
+ bytes10 oldValue = container.extract_32_10(offset);
+
+ assertEq(newValue, container.replace_32_10(newValue, offset).extract_32_10(offset));
+ assertEq(container, container.replace_32_10(newValue, offset).replace_32_10(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes12 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 20));
+
+ bytes12 oldValue = container.extract_32_12(offset);
+
+ assertEq(newValue, container.replace_32_12(newValue, offset).extract_32_12(offset));
+ assertEq(container, container.replace_32_12(newValue, offset).replace_32_12(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes16 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 16));
+
+ bytes16 oldValue = container.extract_32_16(offset);
+
+ assertEq(newValue, container.replace_32_16(newValue, offset).extract_32_16(offset));
+ assertEq(container, container.replace_32_16(newValue, offset).replace_32_16(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes20 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 12));
+
+ bytes20 oldValue = container.extract_32_20(offset);
+
+ assertEq(newValue, container.replace_32_20(newValue, offset).extract_32_20(offset));
+ assertEq(container, container.replace_32_20(newValue, offset).replace_32_20(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes22 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 10));
+
+ bytes22 oldValue = container.extract_32_22(offset);
+
+ assertEq(newValue, container.replace_32_22(newValue, offset).extract_32_22(offset));
+ assertEq(container, container.replace_32_22(newValue, offset).replace_32_22(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes24 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 8));
+
+ bytes24 oldValue = container.extract_32_24(offset);
+
+ assertEq(newValue, container.replace_32_24(newValue, offset).extract_32_24(offset));
+ assertEq(container, container.replace_32_24(newValue, offset).replace_32_24(oldValue, offset));
+ }
+
+ function testReplace(bytes32 container, bytes28 newValue, uint8 offset) external pure {
+ offset = uint8(bound(offset, 0, 4));
+
+ bytes28 oldValue = container.extract_32_28(offset);
+
+ assertEq(newValue, container.replace_32_28(newValue, offset).extract_32_28(offset));
+ assertEq(container, container.replace_32_28(newValue, offset).replace_32_28(oldValue, offset));
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Packing.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Packing.test.js
new file mode 100644
index 000000000..dd36f45d7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Packing.test.js
@@ -0,0 +1,70 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { forceDeployCode } = require('../helpers/deploy');
+const { product } = require('../helpers/iterate');
+const { SIZES } = require('../../scripts/generate/templates/Packing.opts');
+
+async function fixture() {
+ return { mock: await forceDeployCode('$Packing') };
+}
+
+describe('Packing', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('pack', function () {
+ for (const [size1, size2] of product(SIZES, SIZES).filter(([size1, size2]) => SIZES.includes(size1 + size2))) {
+ const value1 = ethers.hexlify(ethers.randomBytes(size1));
+ const value2 = ethers.hexlify(ethers.randomBytes(size2));
+ const packed = ethers.concat([value1, value2]);
+
+ it(`pack bytes${size1} + bytes${size2} => bytes${size1 + size2}`, async function () {
+ expect(await this.mock[`$pack_${size1}_${size2}`](value1, value2)).to.equal(packed);
+ expect(await this.mock[`$extract_${size1 + size2}_${size1}`](packed, 0)).to.equal(value1);
+ expect(await this.mock[`$extract_${size1 + size2}_${size2}`](packed, size1)).to.equal(value2);
+ });
+ }
+ });
+
+ describe('extract / replace', function () {
+ for (const [size1, size2] of product(SIZES, SIZES).filter(([size1, size2]) => size1 > size2)) {
+ const MAX_OFFSET = size1 - size2;
+ const offset = ethers.toNumber(ethers.randomBytes(1)) % (MAX_OFFSET + 1);
+ const outer = ethers.randomBytes(size1);
+ const value = ethers.randomBytes(size2);
+
+ it(`extract bytes${size2} from bytes${size1}`, async function () {
+ expect(await this.mock[`$extract_${size1}_${size2}`](outer, offset)).to.equal(
+ ethers.hexlify(outer.slice(offset, offset + size2)),
+ );
+
+ await expect(this.mock[`$extract_${size1}_${size2}`](outer, MAX_OFFSET)).to.not.be.revertedWithCustomError(
+ this.mock,
+ 'OutOfRangeAccess',
+ );
+
+ await expect(this.mock[`$extract_${size1}_${size2}`](outer, MAX_OFFSET + 1)).to.be.revertedWithCustomError(
+ this.mock,
+ 'OutOfRangeAccess',
+ );
+ });
+
+ it(`replace bytes${size2} from bytes${size1}`, async function () {
+ expect(await this.mock[`$replace_${size1}_${size2}`](outer, value, offset)).to.equal(
+ ethers.concat([outer.slice(0, offset), value, outer.slice(offset + size2)]),
+ );
+
+ await expect(
+ this.mock[`$replace_${size1}_${size2}`](outer, value, MAX_OFFSET),
+ ).to.not.be.revertedWithCustomError(this.mock, 'OutOfRangeAccess');
+
+ await expect(
+ this.mock[`$replace_${size1}_${size2}`](outer, value, MAX_OFFSET + 1),
+ ).to.be.revertedWithCustomError(this.mock, 'OutOfRangeAccess');
+ });
+ }
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Panic.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Panic.test.js
new file mode 100644
index 000000000..49673c751
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Panic.test.js
@@ -0,0 +1,37 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+async function fixture() {
+ return { mock: await ethers.deployContract('$Panic') };
+}
+
+describe('Panic', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const [name, code] of Object.entries({
+ GENERIC: 0x0,
+ ASSERT: PANIC_CODES.ASSERTION_ERROR,
+ UNDER_OVERFLOW: PANIC_CODES.ARITHMETIC_OVERFLOW,
+ DIVISION_BY_ZERO: PANIC_CODES.DIVISION_BY_ZERO,
+ ENUM_CONVERSION_ERROR: PANIC_CODES.ENUM_CONVERSION_OUT_OF_BOUNDS,
+ STORAGE_ENCODING_ERROR: PANIC_CODES.INCORRECTLY_ENCODED_STORAGE_BYTE_ARRAY,
+ EMPTY_ARRAY_POP: PANIC_CODES.POP_ON_EMPTY_ARRAY,
+ ARRAY_OUT_OF_BOUNDS: PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS,
+ RESOURCE_ERROR: PANIC_CODES.TOO_MUCH_MEMORY_ALLOCATED,
+ INVALID_INTERNAL_FUNCTION: PANIC_CODES.ZERO_INITIALIZED_VARIABLE,
+ })) {
+ describe(`${name} (${ethers.toBeHex(code)})`, function () {
+ it('exposes panic code as constant', async function () {
+ expect(await this.mock.getFunction(`$${name}`)()).to.equal(code);
+ });
+
+ it('reverts with panic when called', async function () {
+ await expect(this.mock.$panic(code)).to.be.revertedWithPanic(code);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Pausable.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Pausable.test.js
new file mode 100644
index 000000000..67d74a0d8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Pausable.test.js
@@ -0,0 +1,90 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const [pauser] = await ethers.getSigners();
+
+ const mock = await ethers.deployContract('PausableMock');
+
+ return { pauser, mock };
+}
+
+describe('Pausable', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('when unpaused', function () {
+ beforeEach(async function () {
+ expect(await this.mock.paused()).to.be.false;
+ });
+
+ it('can perform normal process in non-pause', async function () {
+ expect(await this.mock.count()).to.equal(0n);
+
+ await this.mock.normalProcess();
+ expect(await this.mock.count()).to.equal(1n);
+ });
+
+ it('cannot take drastic measure in non-pause', async function () {
+ await expect(this.mock.drasticMeasure()).to.be.revertedWithCustomError(this.mock, 'ExpectedPause');
+
+ expect(await this.mock.drasticMeasureTaken()).to.be.false;
+ });
+
+ describe('when paused', function () {
+ beforeEach(async function () {
+ this.tx = await this.mock.pause();
+ });
+
+ it('emits a Paused event', async function () {
+ await expect(this.tx).to.emit(this.mock, 'Paused').withArgs(this.pauser);
+ });
+
+ it('cannot perform normal process in pause', async function () {
+ await expect(this.mock.normalProcess()).to.be.revertedWithCustomError(this.mock, 'EnforcedPause');
+ });
+
+ it('can take a drastic measure in a pause', async function () {
+ await this.mock.drasticMeasure();
+ expect(await this.mock.drasticMeasureTaken()).to.be.true;
+ });
+
+ it('reverts when re-pausing', async function () {
+ await expect(this.mock.pause()).to.be.revertedWithCustomError(this.mock, 'EnforcedPause');
+ });
+
+ describe('unpausing', function () {
+ it('is unpausable by the pauser', async function () {
+ await this.mock.unpause();
+ expect(await this.mock.paused()).to.be.false;
+ });
+
+ describe('when unpaused', function () {
+ beforeEach(async function () {
+ this.tx = await this.mock.unpause();
+ });
+
+ it('emits an Unpaused event', async function () {
+ await expect(this.tx).to.emit(this.mock, 'Unpaused').withArgs(this.pauser);
+ });
+
+ it('should resume allowing normal process', async function () {
+ expect(await this.mock.count()).to.equal(0n);
+ await this.mock.normalProcess();
+ expect(await this.mock.count()).to.equal(1n);
+ });
+
+ it('should prevent drastic measure', async function () {
+ await expect(this.mock.drasticMeasure()).to.be.revertedWithCustomError(this.mock, 'ExpectedPause');
+ });
+
+ it('reverts when re-unpausing', async function () {
+ await expect(this.mock.unpause()).to.be.revertedWithCustomError(this.mock, 'ExpectedPause');
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ReentrancyGuard.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ReentrancyGuard.test.js
new file mode 100644
index 000000000..c4418563e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ReentrancyGuard.test.js
@@ -0,0 +1,50 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+for (const variant of ['', 'Transient']) {
+ describe(`Reentrancy${variant}Guard`, function () {
+ async function fixture() {
+ const name = `Reentrancy${variant}Mock`;
+ const mock = await ethers.deployContract(name);
+ return { name, mock };
+ }
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('nonReentrant function can be called', async function () {
+ expect(await this.mock.counter()).to.equal(0n);
+ await this.mock.callback();
+ expect(await this.mock.counter()).to.equal(1n);
+ });
+
+ it('does not allow remote callback', async function () {
+ const attacker = await ethers.deployContract('ReentrancyAttack');
+ await expect(this.mock.countAndCall(attacker)).to.be.revertedWith('ReentrancyAttack: failed call');
+ });
+
+ it('_reentrancyGuardEntered should be true when guarded', async function () {
+ await this.mock.guardedCheckEntered();
+ });
+
+ it('_reentrancyGuardEntered should be false when unguarded', async function () {
+ await this.mock.unguardedCheckNotEntered();
+ });
+
+ // The following are more side-effects than intended behavior:
+ // I put them here as documentation, and to monitor any changes
+ // in the side-effects.
+ it('does not allow local recursion', async function () {
+ await expect(this.mock.countLocalRecursive(10n)).to.be.revertedWithCustomError(
+ this.mock,
+ 'ReentrancyGuardReentrantCall',
+ );
+ });
+
+ it('does not allow indirect local recursion', async function () {
+ await expect(this.mock.countThisRecursive(10n)).to.be.revertedWith(`${this.name}: failed call`);
+ });
+ });
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ShortStrings.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ShortStrings.t.sol
new file mode 100644
index 000000000..4aeafd721
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ShortStrings.t.sol
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {SymTest} from "halmos-cheatcodes/SymTest.sol";
+
+import {ShortStrings, ShortString} from "@openzeppelin/contracts/utils/ShortStrings.sol";
+
+contract ShortStringsTest is Test, SymTest {
+ string _fallback;
+
+ function testRoundtripShort(string memory input) external {
+ vm.assume(_isShort(input));
+ _assertRoundtripShort(input);
+ }
+
+ function symbolicRoundtripShort() external {
+ string memory input = svm.createString(31, "RoundtripShortInput");
+ _assertRoundtripShort(input);
+ }
+
+ function testRoundtripWithFallback(string memory input, string memory fallbackInitial) external {
+ _assertRoundtripWithFallback(input, fallbackInitial);
+ }
+
+ function symbolicRoundtripWithFallbackLong() external {
+ string memory input = svm.createString(256, "RoundtripWithFallbackInput");
+ string memory fallbackInitial = svm.createString(256, "RoundtripWithFallbackFallbackInitial");
+ _assertRoundtripWithFallback(input, fallbackInitial);
+ }
+
+ function symbolicRoundtripWithFallbackShort() external {
+ string memory input = svm.createString(31, "RoundtripWithFallbackInput");
+ string memory fallbackInitial = svm.createString(31, "RoundtripWithFallbackFallbackInitial");
+ _assertRoundtripWithFallback(input, fallbackInitial);
+ }
+
+ function testRevertLong(string memory input) external {
+ vm.assume(!_isShort(input));
+ _assertRevertLong(input);
+ }
+
+ function testLengthShort(string memory input) external {
+ vm.assume(_isShort(input));
+ _assertLengthShort(input);
+ }
+
+ function symbolicLengthShort() external {
+ string memory input = svm.createString(31, "LengthShortInput");
+ _assertLengthShort(input);
+ }
+
+ function testLengthWithFallback(string memory input, string memory fallbackInitial) external {
+ _fallback = fallbackInitial;
+ _assertLengthWithFallback(input);
+ }
+
+ function symbolicLengthWithFallback() external {
+ uint256 length = 256;
+ string memory input = svm.createString(length, "LengthWithFallbackInput");
+ string memory fallbackInitial = svm.createString(length, "LengthWithFallbackFallbackInitial");
+ _fallback = fallbackInitial;
+ _assertLengthWithFallback(input);
+ }
+
+ /// Assertions
+
+ function _assertRoundtripShort(string memory input) internal {
+ ShortString short = ShortStrings.toShortString(input);
+ string memory output = ShortStrings.toString(short);
+ assertEq(input, output);
+ }
+
+ function _assertRoundtripWithFallback(string memory input, string memory fallbackInitial) internal {
+ _fallback = fallbackInitial; // Make sure that the initial value has no effect
+ ShortString short = ShortStrings.toShortStringWithFallback(input, _fallback);
+ string memory output = ShortStrings.toStringWithFallback(short, _fallback);
+ assertEq(input, output);
+ }
+
+ function _assertRevertLong(string memory input) internal {
+ vm.expectRevert(abi.encodeWithSelector(ShortStrings.StringTooLong.selector, input));
+ this.toShortString(input);
+ }
+
+ function _assertLengthShort(string memory input) internal {
+ ShortString short = ShortStrings.toShortString(input);
+ uint256 shortLength = ShortStrings.byteLength(short);
+ uint256 inputLength = bytes(input).length;
+ assertEq(inputLength, shortLength);
+ }
+
+ function _assertLengthWithFallback(string memory input) internal {
+ uint256 inputLength = bytes(input).length;
+ ShortString short = ShortStrings.toShortStringWithFallback(input, _fallback);
+ uint256 shortLength = ShortStrings.byteLengthWithFallback(short, _fallback);
+ assertEq(inputLength, shortLength);
+ }
+
+ /// Helpers
+ function toShortString(string memory input) external pure returns (ShortString) {
+ return ShortStrings.toShortString(input);
+ }
+
+ function _isShort(string memory input) internal pure returns (bool) {
+ return bytes(input).length < 32;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ShortStrings.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ShortStrings.test.js
new file mode 100644
index 000000000..cb1a06aa5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/ShortStrings.test.js
@@ -0,0 +1,64 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const FALLBACK_SENTINEL = ethers.zeroPadValue('0xFF', 32);
+
+const length = sstr => parseInt(sstr.slice(64), 16);
+const decode = sstr => ethers.toUtf8String(sstr).slice(0, length(sstr));
+const encode = str =>
+ str.length < 32
+ ? ethers.concat([
+ ethers.encodeBytes32String(str).slice(0, -2),
+ ethers.zeroPadValue(ethers.toBeArray(str.length), 1),
+ ])
+ : FALLBACK_SENTINEL;
+
+async function fixture() {
+ const mock = await ethers.deployContract('$ShortStrings');
+ return { mock };
+}
+
+describe('ShortStrings', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const str of [0, 1, 16, 31, 32, 64, 1024].map(length => 'a'.repeat(length))) {
+ describe(`with string length ${str.length}`, function () {
+ it('encode / decode', async function () {
+ if (str.length < 32) {
+ const encoded = await this.mock.$toShortString(str);
+ expect(encoded).to.equal(encode(str));
+ expect(decode(encoded)).to.equal(str);
+
+ expect(await this.mock.$byteLength(encoded)).to.equal(str.length);
+ expect(await this.mock.$toString(encoded)).to.equal(str);
+ } else {
+ await expect(this.mock.$toShortString(str))
+ .to.be.revertedWithCustomError(this.mock, 'StringTooLong')
+ .withArgs(str);
+ }
+ });
+
+ it('set / get with fallback', async function () {
+ const short = await this.mock
+ .$toShortStringWithFallback(str, 0)
+ .then(tx => tx.wait())
+ .then(receipt => receipt.logs.find(ev => ev.fragment.name == 'return$toShortStringWithFallback').args[0]);
+
+ expect(short).to.equal(encode(str));
+
+ const promise = this.mock.$toString(short);
+ if (str.length < 32) {
+ expect(await promise).to.equal(str);
+ } else {
+ await expect(promise).to.be.revertedWithCustomError(this.mock, 'InvalidShortString');
+ }
+
+ expect(await this.mock.$byteLengthWithFallback(short, 0)).to.equal(str.length);
+ expect(await this.mock.$toStringWithFallback(short, 0)).to.equal(str);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/SlotDerivation.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/SlotDerivation.t.sol
new file mode 100644
index 000000000..4021f0f87
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/SlotDerivation.t.sol
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/SlotDerivation.t.js.
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {SymTest} from "halmos-cheatcodes/SymTest.sol";
+import {SlotDerivation} from "@openzeppelin/contracts/utils/SlotDerivation.sol";
+
+contract SlotDerivationTest is Test, SymTest {
+ using SlotDerivation for bytes32;
+
+ bytes[] private _array;
+
+ function symbolicDeriveArray(uint256 length, uint256 offset) public {
+ vm.assume(length > 0);
+ vm.assume(offset < length);
+ _assertDeriveArray(length, offset);
+ }
+
+ function testDeriveArray(uint256 length, uint256 offset) public {
+ length = bound(length, 1, type(uint256).max);
+ offset = bound(offset, 0, length - 1);
+ _assertDeriveArray(length, offset);
+ }
+
+ function _assertDeriveArray(uint256 length, uint256 offset) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _array.slot
+ sstore(baseSlot, length) // store length so solidity access does not revert
+ }
+
+ bytes storage derived = _array[offset];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveArray().offset(offset), derivedSlot);
+ }
+
+ mapping(address => bytes) private _addressMapping;
+
+ function testSymbolicDeriveMappingAddress(address key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _addressMapping.slot
+ }
+
+ bytes storage derived = _addressMapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(bool => bytes) private _boolMapping;
+
+ function testSymbolicDeriveMappingBoolean(bool key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _boolMapping.slot
+ }
+
+ bytes storage derived = _boolMapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(bytes32 => bytes) private _bytes32Mapping;
+
+ function testSymbolicDeriveMappingBytes32(bytes32 key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _bytes32Mapping.slot
+ }
+
+ bytes storage derived = _bytes32Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(bytes4 => bytes) private _bytes4Mapping;
+
+ function testSymbolicDeriveMappingBytes4(bytes4 key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _bytes4Mapping.slot
+ }
+
+ bytes storage derived = _bytes4Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(uint256 => bytes) private _uint256Mapping;
+
+ function testSymbolicDeriveMappingUint256(uint256 key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _uint256Mapping.slot
+ }
+
+ bytes storage derived = _uint256Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(uint32 => bytes) private _uint32Mapping;
+
+ function testSymbolicDeriveMappingUint32(uint32 key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _uint32Mapping.slot
+ }
+
+ bytes storage derived = _uint32Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(int256 => bytes) private _int256Mapping;
+
+ function testSymbolicDeriveMappingInt256(int256 key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _int256Mapping.slot
+ }
+
+ bytes storage derived = _int256Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(int32 => bytes) private _int32Mapping;
+
+ function testSymbolicDeriveMappingInt32(int32 key) public {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _int32Mapping.slot
+ }
+
+ bytes storage derived = _int32Mapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(string => bytes) private _stringMapping;
+
+ function testDeriveMappingString(string memory key) public {
+ _assertDeriveMappingString(key);
+ }
+
+ function symbolicDeriveMappingString() public {
+ _assertDeriveMappingString(svm.createString(256, "DeriveMappingStringInput"));
+ }
+
+ function _assertDeriveMappingString(string memory key) internal {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _stringMapping.slot
+ }
+
+ bytes storage derived = _stringMapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ mapping(bytes => bytes) private _bytesMapping;
+
+ function testDeriveMappingBytes(bytes memory key) public {
+ _assertDeriveMappingBytes(key);
+ }
+
+ function symbolicDeriveMappingBytes() public {
+ _assertDeriveMappingBytes(svm.createBytes(256, "DeriveMappingBytesInput"));
+ }
+
+ function _assertDeriveMappingBytes(bytes memory key) internal {
+ bytes32 baseSlot;
+ assembly {
+ baseSlot := _bytesMapping.slot
+ }
+
+ bytes storage derived = _bytesMapping[key];
+ bytes32 derivedSlot;
+ assembly {
+ derivedSlot := derived.slot
+ }
+
+ assertEq(baseSlot.deriveMapping(key), derivedSlot);
+ }
+
+ function testSymbolicDeriveMappingBooleanDirty(bytes32 dirtyKey) public {
+ bool key;
+ assembly {
+ key := dirtyKey
+ }
+
+ // run the "normal" test using a potentially dirty value
+ testSymbolicDeriveMappingBoolean(key);
+ }
+
+ function testSymbolicDeriveMappingAddressDirty(bytes32 dirtyKey) public {
+ address key;
+ assembly {
+ key := dirtyKey
+ }
+
+ // run the "normal" test using a potentially dirty value
+ testSymbolicDeriveMappingAddress(key);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/SlotDerivation.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/SlotDerivation.test.js
new file mode 100644
index 000000000..22582b375
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/SlotDerivation.test.js
@@ -0,0 +1,58 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { erc7201Slot } = require('../helpers/storage');
+const { generators } = require('../helpers/random');
+
+async function fixture() {
+ const [account] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$SlotDerivation');
+ return { mock, account };
+}
+
+describe('SlotDerivation', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('namespaces', function () {
+ const namespace = 'example.main';
+
+ it('erc-7201', async function () {
+ expect(await this.mock.$erc7201Slot(namespace)).to.equal(erc7201Slot(namespace));
+ });
+ });
+
+ describe('derivation', function () {
+ it('offset', async function () {
+ const base = generators.bytes32();
+ const offset = generators.uint256();
+ expect(await this.mock.$offset(base, offset)).to.equal((ethers.toBigInt(base) + offset) & ethers.MaxUint256);
+ });
+
+ it('array', async function () {
+ const base = generators.bytes32();
+ expect(await this.mock.$deriveArray(base)).to.equal(ethers.keccak256(base));
+ });
+
+ describe('mapping', function () {
+ for (const { type, key, isValueType } of [
+ { type: 'bool', key: true, isValueType: true },
+ { type: 'address', key: generators.address(), isValueType: true },
+ { type: 'bytes32', key: generators.bytes32(), isValueType: true },
+ { type: 'uint256', key: generators.uint256(), isValueType: true },
+ { type: 'int256', key: generators.int256(), isValueType: true },
+ { type: 'bytes', key: generators.hexBytes(128), isValueType: false },
+ { type: 'string', key: 'lorem ipsum', isValueType: false },
+ ]) {
+ it(type, async function () {
+ const base = generators.bytes32();
+ const expected = isValueType
+ ? ethers.keccak256(ethers.AbiCoder.defaultAbiCoder().encode([type, 'bytes32'], [key, base]))
+ : ethers.solidityPackedKeccak256([type, 'bytes32'], [key, base]);
+ expect(await this.mock[`$deriveMapping(bytes32,${type})`](base, key)).to.equal(expected);
+ });
+ }
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/StorageSlot.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/StorageSlot.test.js
new file mode 100644
index 000000000..ddcf305d1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/StorageSlot.test.js
@@ -0,0 +1,73 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { generators } = require('../helpers/random');
+
+const slot = ethers.id('some.storage.slot');
+const otherSlot = ethers.id('some.other.storage.slot');
+
+const TYPES = [
+ { name: 'Boolean', type: 'bool', value: true, isValueType: true, zero: false },
+ { name: 'Address', type: 'address', value: generators.address(), isValueType: true, zero: generators.address.zero },
+ { name: 'Bytes32', type: 'bytes32', value: generators.bytes32(), isValueType: true, zero: generators.bytes32.zero },
+ { name: 'Uint256', type: 'uint256', value: generators.uint256(), isValueType: true, zero: generators.uint256.zero },
+ { name: 'Int256', type: 'int256', value: generators.int256(), isValueType: true, zero: generators.int256.zero },
+ { name: 'Bytes', type: 'bytes', value: generators.hexBytes(128), isValueType: false, zero: generators.hexBytes.zero },
+ { name: 'String', type: 'string', value: 'lorem ipsum', isValueType: false, zero: '' },
+];
+
+async function fixture() {
+ return { mock: await ethers.deployContract('StorageSlotMock') };
+}
+
+describe('StorageSlot', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const { name, type, value, zero } of TYPES) {
+ describe(`${type} storage slot`, function () {
+ it('set', async function () {
+ await this.mock.getFunction(`set${name}Slot`)(slot, value);
+ });
+
+ describe('get', function () {
+ beforeEach(async function () {
+ await this.mock.getFunction(`set${name}Slot`)(slot, value);
+ });
+
+ it('from right slot', async function () {
+ expect(await this.mock.getFunction(`get${name}Slot`)(slot)).to.equal(value);
+ });
+
+ it('from other slot', async function () {
+ expect(await this.mock.getFunction(`get${name}Slot`)(otherSlot)).to.equal(zero);
+ });
+ });
+ });
+ }
+
+ for (const { name, type, value, zero } of TYPES.filter(type => !type.isValueType)) {
+ describe(`${type} storage pointer`, function () {
+ it('set', async function () {
+ await this.mock.getFunction(`set${name}Storage`)(slot, value);
+ });
+
+ describe('get', function () {
+ beforeEach(async function () {
+ await this.mock.getFunction(`set${name}Storage`)(slot, value);
+ });
+
+ it('from right slot', async function () {
+ expect(await this.mock.getFunction(`${type}Map`)(slot)).to.equal(value);
+ expect(await this.mock.getFunction(`get${name}Storage`)(slot)).to.equal(value);
+ });
+
+ it('from other slot', async function () {
+ expect(await this.mock.getFunction(`${type}Map`)(otherSlot)).to.equal(zero);
+ expect(await this.mock.getFunction(`get${name}Storage`)(otherSlot)).to.equal(zero);
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Strings.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Strings.t.sol
new file mode 100644
index 000000000..f59e675cd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Strings.t.sol
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+
+import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
+
+contract StringsTest is Test {
+ using Strings for *;
+
+ function testParse(uint256 value) external {
+ assertEq(value, value.toString().parseUint());
+ }
+
+ function testParseSigned(int256 value) external {
+ assertEq(value, value.toStringSigned().parseInt());
+ }
+
+ function testParseHex(uint256 value) external {
+ assertEq(value, value.toHexString().parseHexUint());
+ }
+
+ function testParseChecksumHex(address value) external {
+ assertEq(value, value.toChecksumHexString().parseAddress());
+ }
+
+ function testTryParseHexUintExtendedEnd(string memory random) external pure {
+ uint256 length = bytes(random).length;
+ assembly ("memory-safe") {
+ mstore(add(add(random, 0x20), length), 0x3030303030303030303030303030303030303030303030303030303030303030)
+ }
+
+ (bool success, ) = random.tryParseHexUint(1, length + 1);
+ assertFalse(success);
+ }
+
+ function testTryParseAddressExtendedEnd(address random, uint256 begin) external pure {
+ begin = bound(begin, 3, 43);
+ string memory input = random.toHexString();
+ uint256 length = bytes(input).length;
+
+ assembly ("memory-safe") {
+ mstore(add(add(input, 0x20), length), 0x3030303030303030303030303030303030303030303030303030303030303030)
+ }
+
+ (bool success, ) = input.tryParseAddress(begin, begin + 40);
+ assertFalse(success);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Strings.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Strings.test.js
new file mode 100644
index 000000000..0b2d87190
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/Strings.test.js
@@ -0,0 +1,342 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Strings');
+ return { mock };
+}
+
+describe('Strings', function () {
+ before(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('toString', function () {
+ const values = [
+ 0n,
+ 7n,
+ 10n,
+ 99n,
+ 100n,
+ 101n,
+ 123n,
+ 4132n,
+ 12345n,
+ 1234567n,
+ 1234567890n,
+ 123456789012345n,
+ 12345678901234567890n,
+ 123456789012345678901234567890n,
+ 1234567890123456789012345678901234567890n,
+ 12345678901234567890123456789012345678901234567890n,
+ 123456789012345678901234567890123456789012345678901234567890n,
+ 1234567890123456789012345678901234567890123456789012345678901234567890n,
+ ];
+
+ describe('uint256', function () {
+ it('converts MAX_UINT256', async function () {
+ const value = ethers.MaxUint256;
+ expect(await this.mock.$toString(value)).to.equal(value.toString(10));
+ expect(await this.mock.$parseUint(value.toString(10))).to.equal(value);
+ expect(await this.mock.$tryParseUint(value.toString(10))).to.deep.equal([true, value]);
+ });
+
+ for (const value of values) {
+ it(`converts ${value}`, async function () {
+ expect(await this.mock.$toString(value)).to.equal(value.toString(10));
+ expect(await this.mock.$parseUint(value.toString(10))).to.equal(value);
+ expect(await this.mock.$tryParseUint(value.toString(10))).to.deep.equal([true, value]);
+ });
+ }
+ });
+
+ describe('int256', function () {
+ it('converts MAX_INT256', async function () {
+ const value = ethers.MaxInt256;
+ expect(await this.mock.$toStringSigned(value)).to.equal(value.toString(10));
+ expect(await this.mock.$parseInt(value.toString(10))).to.equal(value);
+ expect(await this.mock.$tryParseInt(value.toString(10))).to.deep.equal([true, value]);
+ });
+
+ it('converts MIN_INT256', async function () {
+ const value = ethers.MinInt256;
+ expect(await this.mock.$toStringSigned(value)).to.equal(value.toString(10));
+ expect(await this.mock.$parseInt(value.toString(10))).to.equal(value);
+ expect(await this.mock.$tryParseInt(value.toString(10))).to.deep.equal([true, value]);
+ });
+
+ for (const value of values) {
+ it(`convert ${value}`, async function () {
+ expect(await this.mock.$toStringSigned(value)).to.equal(value.toString(10));
+ expect(await this.mock.$parseInt(value.toString(10))).to.equal(value);
+ expect(await this.mock.$tryParseInt(value.toString(10))).to.deep.equal([true, value]);
+ });
+
+ it(`convert negative ${value}`, async function () {
+ const negated = -value;
+ expect(await this.mock.$toStringSigned(negated)).to.equal(negated.toString(10));
+ expect(await this.mock.$parseInt(negated.toString(10))).to.equal(negated);
+ expect(await this.mock.$tryParseInt(negated.toString(10))).to.deep.equal([true, negated]);
+ });
+ }
+ });
+ });
+
+ describe('toHexString', function () {
+ it('converts 0', async function () {
+ const value = 0n;
+ const string = ethers.toBeHex(value); // 0x00
+
+ expect(await this.mock.getFunction('$toHexString(uint256)')(value)).to.equal(string);
+ expect(await this.mock.$parseHexUint(string)).to.equal(value);
+ expect(await this.mock.$parseHexUint(string.replace(/0x/, ''))).to.equal(value);
+ expect(await this.mock.$tryParseHexUint(string)).to.deep.equal([true, value]);
+ expect(await this.mock.$tryParseHexUint(string.replace(/0x/, ''))).to.deep.equal([true, value]);
+ });
+
+ it('converts a positive number', async function () {
+ const value = 0x4132n;
+ const string = ethers.toBeHex(value);
+
+ expect(await this.mock.getFunction('$toHexString(uint256)')(value)).to.equal(string);
+ expect(await this.mock.$parseHexUint(string)).to.equal(value);
+ expect(await this.mock.$parseHexUint(string.replace(/0x/, ''))).to.equal(value);
+ expect(await this.mock.$tryParseHexUint(string)).to.deep.equal([true, value]);
+ expect(await this.mock.$tryParseHexUint(string.replace(/0x/, ''))).to.deep.equal([true, value]);
+ });
+
+ it('converts MAX_UINT256', async function () {
+ const value = ethers.MaxUint256;
+ const string = ethers.toBeHex(value);
+
+ expect(await this.mock.getFunction('$toHexString(uint256)')(value)).to.equal(string);
+ expect(await this.mock.$parseHexUint(string)).to.equal(value);
+ expect(await this.mock.$parseHexUint(string.replace(/0x/, ''))).to.equal(value);
+ expect(await this.mock.$tryParseHexUint(string)).to.deep.equal([true, value]);
+ expect(await this.mock.$tryParseHexUint(string.replace(/0x/, ''))).to.deep.equal([true, value]);
+ });
+ });
+
+ describe('toHexString fixed', function () {
+ it('converts a positive number (long)', async function () {
+ expect(await this.mock.getFunction('$toHexString(uint256,uint256)')(0x4132n, 32n)).to.equal(
+ '0x0000000000000000000000000000000000000000000000000000000000004132',
+ );
+ });
+
+ it('converts a positive number (short)', async function () {
+ const length = 1n;
+ await expect(this.mock.getFunction('$toHexString(uint256,uint256)')(0x4132n, length))
+ .to.be.revertedWithCustomError(this.mock, 'StringsInsufficientHexLength')
+ .withArgs(0x4132, length);
+ });
+
+ it('converts MAX_UINT256', async function () {
+ expect(await this.mock.getFunction('$toHexString(uint256,uint256)')(ethers.MaxUint256, 32n)).to.equal(
+ ethers.toBeHex(ethers.MaxUint256),
+ );
+ });
+ });
+
+ describe('addresses', function () {
+ const addresses = [
+ '0xa9036907dccae6a1e0033479b12e837e5cf5a02f', // Random address
+ '0x0000e0ca771e21bd00057f54a68c30d400000000', // Leading and trailing zeros
+ // EIP-55 reference
+ '0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed',
+ '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
+ '0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB',
+ '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb',
+ '0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359',
+ '0x52908400098527886E0F7030069857D2E4169EE7',
+ '0x8617E340B3D01FA5F11F306F4090FD50E238070D',
+ '0xde709f2102306220921060314715629080e2fb77',
+ '0x27b1fdb04752bbc536007a920d24acb045561c26',
+ '0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed',
+ '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359',
+ '0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB',
+ '0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb',
+ ];
+
+ describe('toHexString', function () {
+ for (const addr of addresses) {
+ it(`converts ${addr}`, async function () {
+ expect(await this.mock.getFunction('$toHexString(address)')(addr)).to.equal(addr.toLowerCase());
+ });
+ }
+ });
+
+ describe('toChecksumHexString', function () {
+ for (const addr of addresses) {
+ it(`converts ${addr}`, async function () {
+ expect(await this.mock.$toChecksumHexString(addr)).to.equal(ethers.getAddress(addr));
+ });
+ }
+ });
+
+ describe('parseAddress', function () {
+ for (const addr of addresses) {
+ it(`converts ${addr}`, async function () {
+ expect(await this.mock.$parseAddress(addr)).to.equal(ethers.getAddress(addr));
+ expect(await this.mock.$tryParseAddress(addr)).to.deep.equal([true, ethers.getAddress(addr)]);
+ });
+ }
+ });
+ });
+
+ describe('equal', function () {
+ it('compares two empty strings', async function () {
+ expect(await this.mock.$equal('', '')).to.be.true;
+ });
+
+ it('compares two equal strings', async function () {
+ expect(await this.mock.$equal('a', 'a')).to.be.true;
+ });
+
+ it('compares two different strings', async function () {
+ expect(await this.mock.$equal('a', 'b')).to.be.false;
+ });
+
+ it('compares two different strings of different lengths', async function () {
+ expect(await this.mock.$equal('a', 'aa')).to.be.false;
+ expect(await this.mock.$equal('aa', 'a')).to.be.false;
+ });
+
+ it('compares two different large strings', async function () {
+ const str1 = 'a'.repeat(201);
+ const str2 = 'a'.repeat(200) + 'b';
+ expect(await this.mock.$equal(str1, str2)).to.be.false;
+ });
+
+ it('compares two equal large strings', async function () {
+ const str1 = 'a'.repeat(201);
+ const str2 = 'a'.repeat(201);
+ expect(await this.mock.$equal(str1, str2)).to.be.true;
+ });
+ });
+
+ describe('Edge cases: invalid parsing', function () {
+ it('parseUint overflow', async function () {
+ await expect(this.mock.$parseUint((ethers.MaxUint256 + 1n).toString(10))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ await expect(this.mock.$tryParseUint((ethers.MaxUint256 + 1n).toString(10))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ });
+
+ it('parseUint invalid character', async function () {
+ await expect(this.mock.$parseUint('0x1')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseUint('1f')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseUint('-10')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseUint('1.0')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseUint('1 000')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ expect(await this.mock.$tryParseUint('0x1')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseUint('1f')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseUint('-10')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseUint('1.0')).deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseUint('1 000')).deep.equal([false, 0n]);
+ });
+
+ it('parseUint invalid range', async function () {
+ expect(this.mock.$parseUint('12', 3, 2)).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ expect(await this.mock.$tryParseUint('12', 3, 2)).to.deep.equal([false, 0n]);
+ });
+
+ it('parseInt overflow', async function () {
+ await expect(this.mock.$parseInt((ethers.MaxUint256 + 1n).toString(10))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ await expect(this.mock.$parseInt((-ethers.MaxUint256 - 1n).toString(10))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ await expect(this.mock.$tryParseInt((ethers.MaxUint256 + 1n).toString(10))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ await expect(this.mock.$tryParseInt((-ethers.MaxUint256 - 1n).toString(10))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ await expect(this.mock.$parseInt((ethers.MaxInt256 + 1n).toString(10))).to.be.revertedWithCustomError(
+ this.mock,
+ 'StringsInvalidChar',
+ );
+ await expect(this.mock.$parseInt((ethers.MinInt256 - 1n).toString(10))).to.be.revertedWithCustomError(
+ this.mock,
+ 'StringsInvalidChar',
+ );
+ expect(await this.mock.$tryParseInt((ethers.MaxInt256 + 1n).toString(10))).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseInt((ethers.MinInt256 - 1n).toString(10))).to.deep.equal([false, 0n]);
+ });
+
+ it('parseInt invalid character', async function () {
+ await expect(this.mock.$parseInt('0x1')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseInt('1f')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseInt('1.0')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseInt('1 000')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ expect(await this.mock.$tryParseInt('0x1')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseInt('1f')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseInt('1.0')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseInt('1 000')).to.deep.equal([false, 0n]);
+ });
+
+ it('parseInt invalid range', async function () {
+ expect(this.mock.$parseInt('-12', 3, 2)).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ expect(await this.mock.$tryParseInt('-12', 3, 2)).to.deep.equal([false, 0n]);
+ });
+
+ it('parseHexUint overflow', async function () {
+ await expect(this.mock.$parseHexUint((ethers.MaxUint256 + 1n).toString(16))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ await expect(this.mock.$tryParseHexUint((ethers.MaxUint256 + 1n).toString(16))).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_OVERFLOW,
+ );
+ });
+
+ it('parseHexUint invalid character', async function () {
+ await expect(this.mock.$parseHexUint('0123456789abcdefg')).to.be.revertedWithCustomError(
+ this.mock,
+ 'StringsInvalidChar',
+ );
+ await expect(this.mock.$parseHexUint('-1')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseHexUint('-f')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseHexUint('-0xf')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseHexUint('1.0')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ await expect(this.mock.$parseHexUint('1 000')).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ expect(await this.mock.$tryParseHexUint('0123456789abcdefg')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseHexUint('-1')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseHexUint('-f')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseHexUint('-0xf')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseHexUint('1.0')).to.deep.equal([false, 0n]);
+ expect(await this.mock.$tryParseHexUint('1 000')).to.deep.equal([false, 0n]);
+ });
+
+ it('parseHexUint invalid begin and end', async function () {
+ expect(this.mock.$parseHexUint('0x', 3, 2)).to.be.revertedWithCustomError(this.mock, 'StringsInvalidChar');
+ expect(await this.mock.$tryParseHexUint('0x', 3, 2)).to.deep.equal([false, 0n]);
+ });
+
+ it('parseAddress invalid format', async function () {
+ for (const addr of [
+ '0x736a507fB2881d6bB62dcA54673CF5295dC07833', // valid
+ '0x736a507fB2881d6-B62dcA54673CF5295dC07833', // invalid char
+ '0x0736a507fB2881d6bB62dcA54673CF5295dC07833', // tooLong
+ '0x36a507fB2881d6bB62dcA54673CF5295dC07833', // tooShort
+ '736a507fB2881d6bB62dcA54673CF5295dC07833', // missingPrefix - supported
+ ]) {
+ if (ethers.isAddress(addr)) {
+ expect(await this.mock.$parseAddress(addr)).to.equal(ethers.getAddress(addr));
+ expect(await this.mock.$tryParseAddress(addr)).to.deep.equal([true, ethers.getAddress(addr)]);
+ } else {
+ await expect(this.mock.$parseAddress(addr)).to.be.revertedWithCustomError(
+ this.mock,
+ 'StringsInvalidAddressFormat',
+ );
+ expect(await this.mock.$tryParseAddress(addr)).to.deep.equal([false, ethers.ZeroAddress]);
+ }
+ }
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/TransientSlot.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/TransientSlot.test.js
new file mode 100644
index 000000000..7b70be375
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/TransientSlot.test.js
@@ -0,0 +1,59 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { generators } = require('../helpers/random');
+
+const slot = ethers.id('some.storage.slot');
+const otherSlot = ethers.id('some.other.storage.slot');
+
+// Non-value types are not supported by the `TransientSlot` library.
+const TYPES = [
+ { name: 'Boolean', type: 'bool', value: true, zero: false },
+ { name: 'Address', type: 'address', value: generators.address(), zero: generators.address.zero },
+ { name: 'Bytes32', type: 'bytes32', value: generators.bytes32(), zero: generators.bytes32.zero },
+ { name: 'Uint256', type: 'uint256', value: generators.uint256(), zero: generators.uint256.zero },
+ { name: 'Int256', type: 'int256', value: generators.int256(), zero: generators.int256.zero },
+];
+
+async function fixture() {
+ return { mock: await ethers.deployContract('TransientSlotMock') };
+}
+
+describe('TransientSlot', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const { name, type, value, zero } of TYPES) {
+ describe(`${type} transient slot`, function () {
+ const load = `tload${name}(bytes32)`;
+ const store = `tstore(bytes32,${type})`;
+ const event = `${name}Value`;
+
+ it('load', async function () {
+ await expect(this.mock[load](slot)).to.emit(this.mock, event).withArgs(slot, zero);
+ });
+
+ it('store and load (2 txs)', async function () {
+ await this.mock[store](slot, value);
+ await expect(this.mock[load](slot)).to.emit(this.mock, event).withArgs(slot, zero);
+ });
+
+ it('store and load (batched)', async function () {
+ await expect(
+ this.mock.multicall([
+ this.mock.interface.encodeFunctionData(store, [slot, value]),
+ this.mock.interface.encodeFunctionData(load, [slot]),
+ this.mock.interface.encodeFunctionData(load, [otherSlot]),
+ ]),
+ )
+ .to.emit(this.mock, event)
+ .withArgs(slot, value)
+ .to.emit(this.mock, event)
+ .withArgs(otherSlot, zero);
+
+ await expect(this.mock[load](slot)).to.emit(this.mock, event).withArgs(slot, zero);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/ECDSA.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/ECDSA.test.js
new file mode 100644
index 000000000..0f2879a86
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/ECDSA.test.js
@@ -0,0 +1,211 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const TEST_MESSAGE = ethers.id('OpenZeppelin');
+const WRONG_MESSAGE = ethers.id('Nope');
+const NON_HASH_MESSAGE = '0xabcd';
+
+async function fixture() {
+ const [signer] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$ECDSA');
+ return { signer, mock };
+}
+
+describe('ECDSA', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('recover with invalid signature', function () {
+ it('with short signature', async function () {
+ await expect(this.mock.$recover(TEST_MESSAGE, '0x1234'))
+ .to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignatureLength')
+ .withArgs(2);
+ });
+
+ it('with long signature', async function () {
+ await expect(
+ this.mock.$recover(
+ TEST_MESSAGE,
+ '0x01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',
+ ),
+ )
+ .to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignatureLength')
+ .withArgs(85);
+ });
+ });
+
+ describe('recover with valid signature', function () {
+ describe('using .sign', function () {
+ it('returns signer address with correct signature', async function () {
+ // Create the signature
+ const signature = await this.signer.signMessage(TEST_MESSAGE);
+
+ // Recover the signer address from the generated message and signature.
+ expect(await this.mock.$recover(ethers.hashMessage(TEST_MESSAGE), signature)).to.equal(this.signer);
+ });
+
+ it('returns signer address with correct signature for arbitrary length message', async function () {
+ // Create the signature
+ const signature = await this.signer.signMessage(NON_HASH_MESSAGE);
+
+ // Recover the signer address from the generated message and signature.
+ expect(await this.mock.$recover(ethers.hashMessage(NON_HASH_MESSAGE), signature)).to.equal(this.signer);
+ });
+
+ it('returns a different address', async function () {
+ const signature = await this.signer.signMessage(TEST_MESSAGE);
+ expect(await this.mock.$recover(WRONG_MESSAGE, signature)).to.not.be.equal(this.signer);
+ });
+
+ it('reverts with invalid signature', async function () {
+ const signature =
+ '0x332ce75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e01c';
+ await expect(this.mock.$recover(TEST_MESSAGE, signature)).to.be.revertedWithCustomError(
+ this.mock,
+ 'ECDSAInvalidSignature',
+ );
+ });
+ });
+
+ describe('with v=27 signature', function () {
+ const signer = '0x2cc1166f6212628A0deEf2B33BEFB2187D35b86c';
+
+ const signatureWithoutV =
+ '0x5d99b6f7f6d1f73d1a26497f2b1c89b24c0993913f86e9a2d02cd69887d9c94f3c880358579d811b21dd1b7fd9bb01c1d81d10e69f0384e675c32b39643be892';
+
+ it('works with correct v value', async function () {
+ const v = '0x1b'; // 27 = 1b.
+ const signature = ethers.concat([signatureWithoutV, v]);
+ expect(await this.mock.$recover(TEST_MESSAGE, signature)).to.equal(signer);
+
+ const { r, s, yParityAndS: vs } = ethers.Signature.from(signature);
+ expect(await this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s)).to.equal(
+ signer,
+ );
+
+ expect(await this.mock.getFunction('$recover(bytes32,bytes32,bytes32)')(TEST_MESSAGE, r, vs)).to.equal(signer);
+ });
+
+ it('rejects incorrect v value', async function () {
+ const v = '0x1c'; // 28 = 1c.
+ const signature = ethers.concat([signatureWithoutV, v]);
+ expect(await this.mock.$recover(TEST_MESSAGE, signature)).to.not.equal(signer);
+
+ const { r, s, yParityAndS: vs } = ethers.Signature.from(signature);
+ expect(
+ await this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s),
+ ).to.not.equal(signer);
+
+ expect(await this.mock.getFunction('$recover(bytes32,bytes32,bytes32)')(TEST_MESSAGE, r, vs)).to.not.equal(
+ signer,
+ );
+ });
+
+ it('reverts wrong v values', async function () {
+ for (const v of ['0x00', '0x01']) {
+ const signature = ethers.concat([signatureWithoutV, v]);
+ await expect(this.mock.$recover(TEST_MESSAGE, signature)).to.be.revertedWithCustomError(
+ this.mock,
+ 'ECDSAInvalidSignature',
+ );
+
+ const { r, s } = ethers.Signature.from(signature);
+ await expect(
+ this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s),
+ ).to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignature');
+ }
+ });
+
+ it('rejects short EIP2098 format', async function () {
+ const v = '0x1b'; // 27 = 1b.
+ const signature = ethers.concat([signatureWithoutV, v]);
+
+ const { compactSerialized } = ethers.Signature.from(signature);
+ await expect(this.mock.$recover(TEST_MESSAGE, compactSerialized))
+ .to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignatureLength')
+ .withArgs(64);
+ });
+ });
+
+ describe('with v=28 signature', function () {
+ const signer = '0x1E318623aB09Fe6de3C9b8672098464Aeda9100E';
+
+ const signatureWithoutV =
+ '0x331fe75a821c982f9127538858900d87d3ec1f9f737338ad67cad133fa48feff48e6fa0c18abc62e42820f05943e47af3e9fbe306ce74d64094bdf1691ee53e0';
+
+ it('works with correct v value', async function () {
+ const v = '0x1c'; // 28 = 1c.
+ const signature = ethers.concat([signatureWithoutV, v]);
+ expect(await this.mock.$recover(TEST_MESSAGE, signature)).to.equal(signer);
+
+ const { r, s, yParityAndS: vs } = ethers.Signature.from(signature);
+ expect(await this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s)).to.equal(
+ signer,
+ );
+
+ expect(await this.mock.getFunction('$recover(bytes32,bytes32,bytes32)')(TEST_MESSAGE, r, vs)).to.equal(signer);
+ });
+
+ it('rejects incorrect v value', async function () {
+ const v = '0x1b'; // 27 = 1b.
+ const signature = ethers.concat([signatureWithoutV, v]);
+ expect(await this.mock.$recover(TEST_MESSAGE, signature)).to.not.equal(signer);
+
+ const { r, s, yParityAndS: vs } = ethers.Signature.from(signature);
+ expect(
+ await this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s),
+ ).to.not.equal(signer);
+
+ expect(await this.mock.getFunction('$recover(bytes32,bytes32,bytes32)')(TEST_MESSAGE, r, vs)).to.not.equal(
+ signer,
+ );
+ });
+
+ it('reverts invalid v values', async function () {
+ for (const v of ['0x00', '0x01']) {
+ const signature = ethers.concat([signatureWithoutV, v]);
+ await expect(this.mock.$recover(TEST_MESSAGE, signature)).to.be.revertedWithCustomError(
+ this.mock,
+ 'ECDSAInvalidSignature',
+ );
+
+ const { r, s } = ethers.Signature.from(signature);
+ await expect(
+ this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s),
+ ).to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignature');
+ }
+ });
+
+ it('rejects short EIP2098 format', async function () {
+ const v = '0x1b'; // 28 = 1b.
+ const signature = ethers.concat([signatureWithoutV, v]);
+
+ const { compactSerialized } = ethers.Signature.from(signature);
+ await expect(this.mock.$recover(TEST_MESSAGE, compactSerialized))
+ .to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignatureLength')
+ .withArgs(64);
+ });
+ });
+
+ it('reverts with high-s value signature', async function () {
+ const message = '0xb94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9';
+
+ const highSSignature =
+ '0xe742ff452d41413616a5bf43fe15dd88294e983d3d36206c2712f39083d638bde0a0fc89be718fbc1033e1d30d78be1c68081562ed2e97af876f286f3453231d1b';
+
+ const r = ethers.dataSlice(highSSignature, 0, 32);
+ const s = ethers.dataSlice(highSSignature, 32, 64);
+ const v = ethers.dataSlice(highSSignature, 64, 65);
+
+ await expect(this.mock.$recover(message, highSSignature))
+ .to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignatureS')
+ .withArgs(s);
+ await expect(this.mock.getFunction('$recover(bytes32,uint8,bytes32,bytes32)')(TEST_MESSAGE, v, r, s))
+ .to.be.revertedWithCustomError(this.mock, 'ECDSAInvalidSignatureS')
+ .withArgs(s);
+ expect(() => ethers.Signature.from(highSSignature)).to.throw('non-canonical s');
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/EIP712.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/EIP712.test.js
new file mode 100644
index 000000000..2b6e7fa97
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/EIP712.test.js
@@ -0,0 +1,105 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { getDomain, domainSeparator, hashTypedData } = require('../../helpers/eip712');
+const { formatType } = require('../../helpers/eip712-types');
+
+const LENGTHS = {
+ short: ['A Name', '1'],
+ long: ['A'.repeat(40), 'B'.repeat(40)],
+};
+
+const fixture = async () => {
+ const [from, to] = await ethers.getSigners();
+
+ const lengths = {};
+ for (const [shortOrLong, [name, version]] of Object.entries(LENGTHS)) {
+ lengths[shortOrLong] = { name, version };
+ lengths[shortOrLong].eip712 = await ethers.deployContract('$EIP712Verifier', [name, version]);
+ lengths[shortOrLong].domain = {
+ name,
+ version,
+ chainId: await ethers.provider.getNetwork().then(({ chainId }) => chainId),
+ verifyingContract: lengths[shortOrLong].eip712.target,
+ };
+ }
+
+ return { from, to, lengths };
+};
+
+describe('EIP712', function () {
+ for (const [shortOrLong, [name, version]] of Object.entries(LENGTHS)) {
+ describe(`with ${shortOrLong} name and version`, function () {
+ beforeEach('deploying', async function () {
+ Object.assign(this, await loadFixture(fixture));
+ Object.assign(this, this.lengths[shortOrLong]);
+ });
+
+ describe('domain separator', function () {
+ it('is internally available', async function () {
+ const expected = await domainSeparator(this.domain);
+
+ expect(await this.eip712.$_domainSeparatorV4()).to.equal(expected);
+ });
+
+ it("can be rebuilt using EIP-5267's eip712Domain", async function () {
+ const rebuildDomain = await getDomain(this.eip712);
+ expect(rebuildDomain).to.be.deep.equal(this.domain);
+ });
+
+ if (shortOrLong === 'short') {
+ // Long strings are in storage, and the proxy will not be properly initialized unless
+ // the upgradeable contract variant is used and the initializer is invoked.
+
+ it('adjusts when behind proxy', async function () {
+ const factory = await ethers.deployContract('$Clones');
+
+ const clone = await factory
+ .$clone(this.eip712)
+ .then(tx => tx.wait())
+ .then(receipt => receipt.logs.find(ev => ev.fragment.name == 'return$clone_address').args.instance)
+ .then(address => ethers.getContractAt('$EIP712Verifier', address));
+
+ const expectedDomain = { ...this.domain, verifyingContract: clone.target };
+ expect(await getDomain(clone)).to.be.deep.equal(expectedDomain);
+
+ const expectedSeparator = await domainSeparator(expectedDomain);
+ expect(await clone.$_domainSeparatorV4()).to.equal(expectedSeparator);
+ });
+ }
+ });
+
+ it('hash digest', async function () {
+ const structhash = ethers.hexlify(ethers.randomBytes(32));
+ expect(await this.eip712.$_hashTypedDataV4(structhash)).to.equal(hashTypedData(this.domain, structhash));
+ });
+
+ it('digest', async function () {
+ const types = {
+ Mail: formatType({
+ to: 'address',
+ contents: 'string',
+ }),
+ };
+
+ const message = {
+ to: this.to.address,
+ contents: 'very interesting',
+ };
+
+ const signature = await this.from.signTypedData(this.domain, types, message);
+
+ await expect(this.eip712.verify(signature, this.from.address, message.to, message.contents)).to.not.be.reverted;
+ });
+
+ it('name', async function () {
+ expect(await this.eip712.$_EIP712Name()).to.equal(name);
+ });
+
+ it('version', async function () {
+ expect(await this.eip712.$_EIP712Version()).to.equal(version);
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/MerkleProof.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/MerkleProof.test.js
new file mode 100644
index 000000000..93ee964a8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/MerkleProof.test.js
@@ -0,0 +1,213 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+const { SimpleMerkleTree } = require('@openzeppelin/merkle-tree');
+
+// generate bytes32 leaves from a string
+const toLeaves = (str, separator = '') => str.split(separator).map(e => ethers.keccak256(ethers.toUtf8Bytes(e)));
+// internal node hashes
+const concatSorted = (...elements) => Buffer.concat(elements.map(ethers.getBytes).sort(Buffer.compare));
+const defaultHash = (a, b) => ethers.keccak256(concatSorted(a, b));
+const customHash = (a, b) => ethers.sha256(concatSorted(a, b));
+
+describe('MerkleProof', function () {
+ for (const { title, contractName, nodeHash } of [
+ { title: 'default hash', contractName: '$MerkleProof', nodeHash: defaultHash },
+ { title: 'custom hash', contractName: '$MerkleProofCustomHashMock', nodeHash: customHash },
+ ]) {
+ describe(title, function () {
+ // stateless: no need for a fixture, just use before
+ before(async function () {
+ this.mock = await ethers.deployContract(contractName);
+ this.makeTree = str => SimpleMerkleTree.of(toLeaves(str), { nodeHash });
+ });
+
+ describe('verify', function () {
+ it('returns true for a valid Merkle proof', async function () {
+ const merkleTree = this.makeTree('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=');
+
+ const root = merkleTree.root;
+ const hash = merkleTree.at(0);
+ const proof = merkleTree.getProof(0);
+
+ expect(await this.mock.$processProof(proof, hash)).to.equal(root);
+ expect(await this.mock.$processProofCalldata(proof, hash)).to.equal(root);
+ expect(await this.mock.$verify(proof, root, hash)).to.be.true;
+ expect(await this.mock.$verifyCalldata(proof, root, hash)).to.be.true;
+
+ // For demonstration, it is also possible to create valid proofs for certain 64-byte values *not* in elements:
+ const noSuchLeaf = nodeHash(hash, proof.at(0));
+
+ expect(await this.mock.$processProof(proof.slice(1), noSuchLeaf)).to.equal(root);
+ expect(await this.mock.$processProofCalldata(proof.slice(1), noSuchLeaf)).to.equal(root);
+ expect(await this.mock.$verify(proof.slice(1), root, noSuchLeaf)).to.be.true;
+ expect(await this.mock.$verifyCalldata(proof.slice(1), root, noSuchLeaf)).to.be.true;
+ });
+
+ it('returns false for an invalid Merkle proof', async function () {
+ const correctMerkleTree = this.makeTree('abc');
+ const otherMerkleTree = this.makeTree('def');
+
+ const root = correctMerkleTree.root;
+ const hash = correctMerkleTree.at(0);
+ const proof = otherMerkleTree.getProof(0);
+
+ expect(await this.mock.$processProof(proof, hash)).to.not.equal(root);
+ expect(await this.mock.$processProofCalldata(proof, hash)).to.not.equal(root);
+ expect(await this.mock.$verify(proof, root, hash)).to.be.false;
+ expect(await this.mock.$verifyCalldata(proof, root, hash)).to.be.false;
+ });
+
+ it('returns false for a Merkle proof of invalid length', async function () {
+ const merkleTree = this.makeTree('abc');
+
+ const root = merkleTree.root;
+ const hash = merkleTree.at(0);
+ const proof = merkleTree.getProof(0);
+ const badProof = proof.slice(0, -1);
+
+ expect(await this.mock.$processProof(badProof, hash)).to.not.equal(root);
+ expect(await this.mock.$processProofCalldata(badProof, hash)).to.not.equal(root);
+ expect(await this.mock.$verify(badProof, root, hash)).to.be.false;
+ expect(await this.mock.$verifyCalldata(badProof, root, hash)).to.be.false;
+ });
+ });
+
+ describe('multiProofVerify', function () {
+ it('returns true for a valid Merkle multi proof', async function () {
+ const merkleTree = this.makeTree('abcdef');
+
+ const root = merkleTree.root;
+ const { proof, proofFlags, leaves } = merkleTree.getMultiProof(toLeaves('bdf'));
+ const hashes = leaves.map(e => merkleTree.leafHash(e));
+
+ expect(await this.mock.$processMultiProof(proof, proofFlags, hashes)).to.equal(root);
+ expect(await this.mock.$processMultiProofCalldata(proof, proofFlags, hashes)).to.equal(root);
+ expect(await this.mock.$multiProofVerify(proof, proofFlags, root, hashes)).to.be.true;
+ expect(await this.mock.$multiProofVerifyCalldata(proof, proofFlags, root, hashes)).to.be.true;
+ });
+
+ it('returns false for an invalid Merkle multi proof', async function () {
+ const merkleTree = this.makeTree('abcdef');
+ const otherMerkleTree = this.makeTree('ghi');
+
+ const root = merkleTree.root;
+ const { proof, proofFlags, leaves } = otherMerkleTree.getMultiProof(toLeaves('ghi'));
+ const hashes = leaves.map(e => merkleTree.leafHash(e));
+
+ expect(await this.mock.$processMultiProof(proof, proofFlags, hashes)).to.not.equal(root);
+ expect(await this.mock.$processMultiProofCalldata(proof, proofFlags, hashes)).to.not.equal(root);
+ expect(await this.mock.$multiProofVerify(proof, proofFlags, root, hashes)).to.be.false;
+ expect(await this.mock.$multiProofVerifyCalldata(proof, proofFlags, root, hashes)).to.be.false;
+ });
+
+ it('revert with invalid multi proof #1', async function () {
+ const merkleTree = this.makeTree('abcd');
+
+ const root = merkleTree.root;
+ const hashA = merkleTree.at(0);
+ const hashB = merkleTree.at(1);
+ const hashCD = nodeHash(merkleTree.at(2), merkleTree.at(3));
+ const hashE = ethers.randomBytes(32); // incorrect (not part of the tree)
+ const fill = ethers.randomBytes(32);
+
+ await expect(
+ this.mock.$processMultiProof([hashB, fill, hashCD], [false, false, false], [hashA, hashE]),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+
+ await expect(
+ this.mock.$processMultiProofCalldata([hashB, fill, hashCD], [false, false, false], [hashA, hashE]),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+
+ await expect(
+ this.mock.$multiProofVerify([hashB, fill, hashCD], [false, false, false], root, [hashA, hashE]),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+
+ await expect(
+ this.mock.$multiProofVerifyCalldata([hashB, fill, hashCD], [false, false, false], root, [hashA, hashE]),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+ });
+
+ it('revert with invalid multi proof #2', async function () {
+ const merkleTree = this.makeTree('abcd');
+
+ const root = merkleTree.root;
+ const hashA = merkleTree.at(0);
+ const hashB = merkleTree.at(1);
+ const hashCD = nodeHash(merkleTree.at(2), merkleTree.at(3));
+ const hashE = ethers.randomBytes(32); // incorrect (not part of the tree)
+ const fill = ethers.randomBytes(32);
+
+ await expect(
+ this.mock.$processMultiProof([hashB, fill, hashCD], [false, false, false, false], [hashE, hashA]),
+ ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+
+ await expect(
+ this.mock.$processMultiProofCalldata([hashB, fill, hashCD], [false, false, false, false], [hashE, hashA]),
+ ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+
+ await expect(
+ this.mock.$multiProofVerify([hashB, fill, hashCD], [false, false, false, false], root, [hashE, hashA]),
+ ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+
+ await expect(
+ this.mock.$multiProofVerifyCalldata([hashB, fill, hashCD], [false, false, false, false], root, [
+ hashE,
+ hashA,
+ ]),
+ ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ });
+
+ it('limit case: works for tree containing a single leaf', async function () {
+ const merkleTree = this.makeTree('a');
+
+ const root = merkleTree.root;
+ const { proof, proofFlags, leaves } = merkleTree.getMultiProof(toLeaves('a'));
+ const hashes = leaves.map(e => merkleTree.leafHash(e));
+
+ expect(await this.mock.$processMultiProof(proof, proofFlags, hashes)).to.equal(root);
+ expect(await this.mock.$processMultiProofCalldata(proof, proofFlags, hashes)).to.equal(root);
+ expect(await this.mock.$multiProofVerify(proof, proofFlags, root, hashes)).to.be.true;
+ expect(await this.mock.$multiProofVerifyCalldata(proof, proofFlags, root, hashes)).to.be.true;
+ });
+
+ it('limit case: can prove empty leaves', async function () {
+ const merkleTree = this.makeTree('abcd');
+
+ const root = merkleTree.root;
+ expect(await this.mock.$processMultiProof([root], [], [])).to.equal(root);
+ expect(await this.mock.$processMultiProofCalldata([root], [], [])).to.equal(root);
+ expect(await this.mock.$multiProofVerify([root], [], root, [])).to.be.true;
+ expect(await this.mock.$multiProofVerifyCalldata([root], [], root, [])).to.be.true;
+ });
+
+ it('reverts processing manipulated proofs with a zero-value node at depth 1', async function () {
+ // Create a merkle tree that contains a zero leaf at depth 1
+ const leave = ethers.id('real leaf');
+ const root = nodeHash(leave, ethers.ZeroHash);
+
+ // Now we can pass any **malicious** fake leaves as valid!
+ const maliciousLeaves = ['malicious', 'leaves'].map(ethers.id).map(ethers.toBeArray).sort(Buffer.compare);
+ const maliciousProof = [leave, leave];
+ const maliciousProofFlags = [true, true, false];
+
+ await expect(
+ this.mock.$processMultiProof(maliciousProof, maliciousProofFlags, maliciousLeaves),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+
+ await expect(
+ this.mock.$processMultiProofCalldata(maliciousProof, maliciousProofFlags, maliciousLeaves),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+
+ await expect(
+ this.mock.$multiProofVerify(maliciousProof, maliciousProofFlags, root, maliciousLeaves),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+
+ await expect(
+ this.mock.$multiProofVerifyCalldata(maliciousProof, maliciousProofFlags, root, maliciousLeaves),
+ ).to.be.revertedWithCustomError(this.mock, 'MerkleProofInvalidMultiproof');
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/MessageHashUtils.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/MessageHashUtils.test.js
new file mode 100644
index 000000000..f20f5a3ca
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/MessageHashUtils.test.js
@@ -0,0 +1,68 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { domainSeparator, hashTypedData } = require('../../helpers/eip712');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$MessageHashUtils');
+ return { mock };
+}
+
+describe('MessageHashUtils', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('toEthSignedMessageHash', function () {
+ it('prefixes bytes32 data correctly', async function () {
+ const message = ethers.randomBytes(32);
+ const expectedHash = ethers.hashMessage(message);
+
+ expect(await this.mock.getFunction('$toEthSignedMessageHash(bytes32)')(message)).to.equal(expectedHash);
+ });
+
+ it('prefixes dynamic length data correctly', async function () {
+ const message = ethers.randomBytes(128);
+ const expectedHash = ethers.hashMessage(message);
+
+ expect(await this.mock.getFunction('$toEthSignedMessageHash(bytes)')(message)).to.equal(expectedHash);
+ });
+
+ it('version match for bytes32', async function () {
+ const message = ethers.randomBytes(32);
+ const fixed = await this.mock.getFunction('$toEthSignedMessageHash(bytes32)')(message);
+ const dynamic = await this.mock.getFunction('$toEthSignedMessageHash(bytes)')(message);
+
+ expect(fixed).to.equal(dynamic);
+ });
+ });
+
+ describe('toDataWithIntendedValidatorHash', function () {
+ it('returns the digest correctly', async function () {
+ const verifier = ethers.Wallet.createRandom().address;
+ const message = ethers.randomBytes(128);
+ const expectedHash = ethers.solidityPackedKeccak256(
+ ['string', 'address', 'bytes'],
+ ['\x19\x00', verifier, message],
+ );
+
+ expect(await this.mock.$toDataWithIntendedValidatorHash(verifier, message)).to.equal(expectedHash);
+ });
+ });
+
+ describe('toTypedDataHash', function () {
+ it('returns the digest correctly', async function () {
+ const domain = {
+ name: 'Test',
+ version: '1',
+ chainId: 1n,
+ verifyingContract: ethers.Wallet.createRandom().address,
+ };
+ const structhash = ethers.randomBytes(32);
+ const expectedHash = hashTypedData(domain, structhash);
+
+ expect(await this.mock.$toTypedDataHash(domainSeparator(domain), structhash)).to.equal(expectedHash);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/P256.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/P256.t.sol
new file mode 100644
index 000000000..0c9b2c78a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/P256.t.sol
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+
+import {P256} from "@openzeppelin/contracts/utils/cryptography/P256.sol";
+import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
+
+contract P256Test is Test {
+ /// forge-config: default.fuzz.runs = 512
+ function testVerify(bytes32 digest, uint256 seed) public {
+ uint256 privateKey = _asPrivateKey(seed);
+
+ (uint256 x, uint256 y) = vm.publicKeyP256(privateKey);
+ (bytes32 r, bytes32 s) = vm.signP256(privateKey, digest);
+ s = _ensureLowerS(s);
+ assertTrue(P256.verify(digest, r, s, bytes32(x), bytes32(y)));
+ assertTrue(P256.verifySolidity(digest, r, s, bytes32(x), bytes32(y)));
+ }
+
+ /// forge-config: default.fuzz.runs = 512
+ function testRecover(bytes32 digest, uint256 seed) public {
+ uint256 privateKey = _asPrivateKey(seed);
+
+ (uint256 x, uint256 y) = vm.publicKeyP256(privateKey);
+ (bytes32 r, bytes32 s) = vm.signP256(privateKey, digest);
+ s = _ensureLowerS(s);
+ (bytes32 qx0, bytes32 qy0) = P256.recovery(digest, 0, r, s);
+ (bytes32 qx1, bytes32 qy1) = P256.recovery(digest, 1, r, s);
+ assertTrue((qx0 == bytes32(x) && qy0 == bytes32(y)) || (qx1 == bytes32(x) && qy1 == bytes32(y)));
+ }
+
+ function _asPrivateKey(uint256 seed) private pure returns (uint256) {
+ return bound(seed, 1, P256.N - 1);
+ }
+
+ function _ensureLowerS(bytes32 s) private pure returns (bytes32) {
+ uint256 _s = uint256(s);
+ unchecked {
+ return _s > P256.N / 2 ? bytes32(P256.N - _s) : s;
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/P256.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/P256.test.js
new file mode 100644
index 000000000..b9655cad3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/P256.test.js
@@ -0,0 +1,156 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { secp256r1 } = require('@noble/curves/p256');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n;
+
+// As in ECDSA, signatures are malleable and the tooling produce both high and low S values.
+// We need to ensure that the s value is in the lower half of the order of the curve.
+const ensureLowerOrderS = ({ s, recovery, ...rest }) => {
+ if (s > N / 2n) {
+ s = N - s;
+ recovery = 1 - recovery;
+ }
+ return { s, recovery, ...rest };
+};
+
+const prepareSignature = (
+ privateKey = secp256r1.utils.randomPrivateKey(),
+ messageHash = ethers.hexlify(ethers.randomBytes(0x20)),
+) => {
+ const publicKey = [
+ secp256r1.getPublicKey(privateKey, false).slice(0x01, 0x21),
+ secp256r1.getPublicKey(privateKey, false).slice(0x21, 0x41),
+ ].map(ethers.hexlify);
+ const { r, s, recovery } = ensureLowerOrderS(secp256r1.sign(messageHash.replace(/0x/, ''), privateKey));
+ const signature = [r, s].map(v => ethers.toBeHex(v, 0x20));
+
+ return { privateKey, publicKey, signature, recovery, messageHash };
+};
+
+describe('P256', function () {
+ async function fixture() {
+ return { mock: await ethers.deployContract('$P256') };
+ }
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('with signature', function () {
+ beforeEach(async function () {
+ Object.assign(this, prepareSignature());
+ });
+
+ it('verify valid signature', async function () {
+ expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.true;
+ expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.true;
+ await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey))
+ .to.be.revertedWithCustomError(this.mock, 'MissingPrecompile')
+ .withArgs('0x0000000000000000000000000000000000000100');
+ });
+
+ it('recover public key', async function () {
+ expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.deep.equal(
+ this.publicKey,
+ );
+ });
+
+ it('reject signature with flipped public key coordinates ([x,y] >> [y,x])', async function () {
+ // flip public key
+ this.publicKey.reverse();
+
+ expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false;
+ expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false;
+ expect(await this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false; // Flipped public key is not in the curve
+ });
+
+ it('reject signature with flipped signature values ([r,s] >> [s,r])', async function () {
+ // Preselected signature where `r < N/2` and `s < N/2`
+ this.signature = [
+ '0x45350225bad31e89db662fcc4fb2f79f349adbb952b3f652eed1f2aa72fb0356',
+ '0x513eb68424c42630012309eee4a3b43e0bdc019d179ef0e0c461800845e237ee',
+ ];
+
+ // Corresponding hash and public key
+ this.messageHash = '0x2ad1f900fe63745deeaedfdf396cb6f0f991c4338a9edf114d52f7d1812040a0';
+ this.publicKey = [
+ '0x9e30de165e521257996425d9bf12a7d366925614bf204eabbb78172b48e52e59',
+ '0x94bf0fe72f99654d7beae4780a520848e306d46a1275b965c4f4c2b8e9a2c08d',
+ ];
+
+ // Make sure it works
+ expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.true;
+
+ // Flip signature
+ this.signature.reverse();
+
+ expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false;
+ expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false;
+ await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey))
+ .to.be.revertedWithCustomError(this.mock, 'MissingPrecompile')
+ .withArgs('0x0000000000000000000000000000000000000100');
+ expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.not.deep.equal(
+ this.publicKey,
+ );
+ });
+
+ it('reject signature with invalid message hash', async function () {
+ // random message hash
+ this.messageHash = ethers.hexlify(ethers.randomBytes(32));
+
+ expect(await this.mock.$verify(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false;
+ expect(await this.mock.$verifySolidity(this.messageHash, ...this.signature, ...this.publicKey)).to.be.false;
+ await expect(this.mock.$verifyNative(this.messageHash, ...this.signature, ...this.publicKey))
+ .to.be.revertedWithCustomError(this.mock, 'MissingPrecompile')
+ .withArgs('0x0000000000000000000000000000000000000100');
+ expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.not.deep.equal(
+ this.publicKey,
+ );
+ });
+
+ it('fail to recover signature with invalid recovery bit', async function () {
+ // flip recovery bit
+ this.recovery = 1 - this.recovery;
+
+ expect(await this.mock.$recovery(this.messageHash, this.recovery, ...this.signature)).to.not.deep.equal(
+ this.publicKey,
+ );
+ });
+ });
+
+ // test cases for https://github.com/C2SP/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/ecdsa_secp256r1_sha256_p1363_test.json
+ describe('wycheproof tests', function () {
+ for (const { key, tests } of require('./ecdsa_secp256r1_sha256_p1363_test.json').testGroups) {
+ // parse public key
+ let [x, y] = [key.wx, key.wy].map(v => ethers.stripZerosLeft('0x' + v, 32));
+ if (x.length > 66 || y.length > 66) continue;
+ x = ethers.zeroPadValue(x, 32);
+ y = ethers.zeroPadValue(y, 32);
+
+ // run all tests for this key
+ for (const { tcId, comment, msg, sig, result } of tests) {
+ // only keep properly formatted signatures
+ if (sig.length != 128) continue;
+
+ it(`${tcId}: ${comment}`, async function () {
+ // split signature, and reduce modulo N
+ let [r, s] = Array(2)
+ .fill()
+ .map((_, i) => ethers.toBigInt('0x' + sig.substring(64 * i, 64 * (i + 1))));
+ // move s to lower part of the curve if needed
+ if (s <= N && s > N / 2n) s = N - s;
+ // prepare signature
+ r = ethers.toBeHex(r, 32);
+ s = ethers.toBeHex(s, 32);
+ // hash
+ const messageHash = ethers.sha256('0x' + msg);
+
+ // check verify
+ expect(await this.mock.$verify(messageHash, r, s, x, y)).to.equal(result == 'valid');
+ });
+ }
+ }
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/RSA.helper.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/RSA.helper.js
new file mode 100644
index 000000000..48c8ee43c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/RSA.helper.js
@@ -0,0 +1,17 @@
+const path = require('path');
+const fs = require('fs');
+
+module.exports = function* parse(file) {
+ const cache = {};
+ const data = fs.readFileSync(path.resolve(__dirname, file), 'utf8');
+ for (const line of data.split('\r\n')) {
+ const groups = line.match(/^(?\w+) = (?\w+)(?.*)$/)?.groups;
+ if (groups) {
+ const { key, value, extra } = groups;
+ cache[key] = value;
+ if (groups.key === 'Result') {
+ yield Object.assign({ extra: extra.trim() }, cache);
+ }
+ }
+ }
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/RSA.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/RSA.test.js
new file mode 100644
index 000000000..bdf33911f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/RSA.test.js
@@ -0,0 +1,102 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { bytes, bytes32 } = ethers.Typed;
+
+const parse = require('./RSA.helper');
+
+async function fixture() {
+ return { mock: await ethers.deployContract('$RSA') };
+}
+
+describe('RSA', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ // Load test cases from file SigVer15_186-3.rsp from:
+ // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/dss/186-2rsatestvectors.zip
+ describe('SigVer15_186-3.rsp tests', function () {
+ for (const test of parse('SigVer15_186-3.rsp')) {
+ const { length } = Buffer.from(test.S, 'hex');
+
+ /// For now, RSA only supports digest that are 32bytes long. If we ever extend that, we can use these hashing functions for @noble:
+ // const { sha1 } = require('@noble/hashes/sha1');
+ // const { sha224, sha256 } = require('@noble/hashes/sha256');
+ // const { sha384, sha512 } = require('@noble/hashes/sha512');
+
+ if (test.SHAAlg === 'SHA256' && length >= 0x100) {
+ const result = test.Result === 'P';
+
+ it(`signature length ${length} ${test.extra} ${result ? 'works' : 'fails'}`, async function () {
+ const data = '0x' + test.Msg;
+ const sig = '0x' + test.S;
+ const exp = '0x' + test.e;
+ const mod = '0x' + test.n;
+
+ expect(await this.mock.$pkcs1Sha256(bytes32(ethers.sha256(data)), sig, exp, mod)).to.equal(result);
+ expect(await this.mock.$pkcs1Sha256(bytes(data), sig, exp, mod)).to.equal(result);
+ });
+ }
+ }
+ });
+
+ describe('others tests', function () {
+ // > openssl genrsa -out private.pem 2048
+ // > openssl rsa -in private.pem -outform der -pubout -out public.pem
+ // > openssl asn1parse -in public.pem -inform DER -strparse 19
+ // > echo -n 'hello world!' | openssl dgst -sha256 -sign private.pem | xxd -p | tr -d \\n
+ const openssl = {
+ descr: 'openssl',
+ data: ethers.toUtf8Bytes('hello world!'),
+ sig: '0x2ff4349940bf0db9bce422e316ac47e3d24b0a869acb05c9c46f74e17491177698b150f2a5996a6bf7d7c73e05af91ad78632115a7d95b823c462596486e56e8473b75a270ca4760cd83f244d5d3af81d2c7d188879abbc2992b22d51e22ffb725f0828c852ee44f81def383e0f92ebfa3c6d97ca5e52a4254f9a886680e3fb394c2a8a955849313dce2cb416f8a67974effd9a17d229146ce10a98684fb3d46a1e53ddaf831cdd2beed895532533c554ae087b2738a5c4cf0802e8062b2a599fd76d67b92eabffa8a92b24e08fbc866217502a4a3d9f6157e491bede3c1048fa8f2d804f66128e8a883018b0ec33a59e1086bf71ae5dc193d9815ca82892dbc',
+ exp: '0x010001',
+ mod: '0xDC1CE5F7B202464CD320B4F9E44FEE0A358BE7022AB155A5BDEE45B1AED3C5A19645D898E294CBA96EAD6929FD8FB4B23E9ADB4D3143A736232C32A8617A77B89F7D8399B9BE37F8349D111067F71D2F20237B9F1A7C1CF44819F9FA5AA030F563DCFB1CC59FFAA86BA2ABEE28D949FED0DF34071B7558950079E28CD9BBA4CAC2F0F86D7BBFB13363C792B5A70C9B279F0B43A264A7CB1A7C7C41FC6EC1D1C1125A6BECE3207AE582F74CE896B9AC18DB00C8985B70145217B831CC313FC06581E186BF70A2EEE2C3C065B5C91A89B2C099B4924CDBF5707D161BD83AC8D9FCA309AC75D63EACF21027C2C9C9F05994331CBDFDD24F9BC6C8B58D8F1824540B',
+ result: true,
+ };
+
+ // According to RFC4055, pg.5 and RFC8017, pg. 64, for SHA-1, and the SHA-2 family,
+ // the algorithm parameter has to be NULL and both explicit NULL parameter and implicit
+ // NULL parameter (ie, absent NULL parameter) are considered to be legal and equivalent.
+ const rfc4055 = {
+ descr: 'rfc8017 implicit null parameter',
+ data: ethers.toUtf8Bytes('hello world!'),
+ sig: '0xa0073057133ff3758e7e111b4d7441f1d8cbe4b2dd5ee4316a14264290dee5ed7f175716639bd9bb43a14e4f9fcb9e84dedd35e2205caac04828b2c053f68176d971ea88534dd2eeec903043c3469fc69c206b2a8694fd262488441ed8852280c3d4994e9d42bd1d575c7024095f1a20665925c2175e089c0d731471f6cc145404edf5559fd2276e45e448086f71c78d0cc6628fad394a34e51e8c10bc39bfe09ed2f5f742cc68bee899d0a41e4c75b7b80afd1c321d89ccd9fe8197c44624d91cc935dfa48de3c201099b5b417be748aef29248527e8bbb173cab76b48478d4177b338fe1f1244e64d7d23f07add560d5ad50b68d6649a49d7bc3db686daaa7',
+ exp: '0x03',
+ mod: '0xe932ac92252f585b3a80a4dd76a897c8b7652952fe788f6ec8dd640587a1ee5647670a8ad4c2be0f9fa6e49c605adf77b5174230af7bd50e5d6d6d6d28ccf0a886a514cc72e51d209cc772a52ef419f6a953f3135929588ebe9b351fca61ced78f346fe00dbb6306e5c2a4c6dfc3779af85ab417371cf34d8387b9b30ae46d7a5ff5a655b8d8455f1b94ae736989d60a6f2fd5cadbffbd504c5a756a2e6bb5cecc13bca7503f6df8b52ace5c410997e98809db4dc30d943de4e812a47553dce54844a78e36401d13f77dc650619fed88d8b3926e3d8e319c80c744779ac5d6abe252896950917476ece5e8fc27d5f053d6018d91b502c4787558a002b9283da7',
+ result: true,
+ };
+
+ const shortN = {
+ descr: 'returns false for a very short n',
+ data: ethers.toUtf8Bytes('hello world!'),
+ sig: '0x0102',
+ exp: '0x03',
+ mod: '0x0405',
+ result: false,
+ };
+
+ const differentLength = {
+ descr: 'returns false for a signature with different length to n',
+ data: ethers.toUtf8Bytes('hello world!'),
+ sig: '0x00112233',
+ exp: '0x03',
+ mod: '0xe932ac92252f585b3a80a4dd76a897c8b7652952fe788f6ec8dd640587a1ee5647670a8ad4c2be0f9fa6e49c605adf77b5174230af7bd50e5d6d6d6d28ccf0a886a514cc72e51d209cc772a52ef419f6a953f3135929588ebe9b351fca61ced78f346fe00dbb6306e5c2a4c6dfc3779af85ab417371cf34d8387b9b30ae46d7a5ff5a655b8d8455f1b94ae736989d60a6f2fd5cadbffbd504c5a756a2e6bb5cecc13bca7503f6df8b52ace5c410997e98809db4dc30d943de4e812a47553dce54844a78e36401d13f77dc650619fed88d8b3926e3d8e319c80c744779ac5d6abe252896950917476ece5e8fc27d5f053d6018d91b502c4787558a002b9283da7',
+ result: false,
+ };
+
+ // this is the openssl example where sig has been replaced by sig + mod
+ const sTooLarge = {
+ ...openssl,
+ descr: 'returns false if s >= n',
+ sig: ethers.toBeHex(ethers.toBigInt(openssl.sig) + ethers.toBigInt(openssl.mod)),
+ result: false,
+ };
+
+ for (const { descr, data, sig, exp, mod, result } of [openssl, rfc4055, shortN, differentLength, sTooLarge]) {
+ it(descr, async function () {
+ expect(await this.mock.$pkcs1Sha256(bytes(data), sig, exp, mod)).to.equal(result);
+ });
+ }
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/SigVer15_186-3.rsp b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/SigVer15_186-3.rsp
new file mode 100644
index 000000000..68e1fdea4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/SigVer15_186-3.rsp
@@ -0,0 +1,3850 @@
+# CAVS 11.0
+# "SigVer PKCS#1 Ver 1.5" information
+# Mod sizes selected: 1024 1536 2048 3072 4096
+# SHA Algorithm selected:SHA1 SHA224 SHA256 SHA384 SHA512
+# Generated on Wed Mar 02 00:13:02 2011
+
+[mod = 1024]
+
+n = a8d68acd413c5e195d5ef04e1b4faaf242365cb450196755e92e1215ba59802aafbadbf2564dd550956abb54f8b1c917844e5f36195d1088c600e07cada5c080ede679f50b3de32cf4026e514542495c54b1903768791aae9e36f082cd38e941ada89baecada61ab0dd37ad536bcb0a0946271594836e92ab5517301d45176b5
+
+p = c107a2fe924b76e206cb9bc4af2ab7008547c00846bf6d0680b3eac3ebcbd0c7fd7a54c2b9899b08f80cde1d3691eaaa2816b1eb11822d6be7beaf4e30977c49
+q = dfea984ce4307eafc0d140c2bb82861e5dbac4f8567cbc981d70440dd639492079031486315e305eb83e591c4a2e96064966f7c894c3ca351925b5ce82d8ef0d
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = a3877b854832d6a6dec749a908e8bd3a73b24372e80321ed01c19ce066117d8efe78ef7168af8acd139e47dd262c0c92ed1701cf6c07e0c1140f82040167f55bb5180c18ad9e66a18dacf0742c1f05173129ed5ac523faeeb2119639cd30ae5a435884b55043d4fb7fa9af0dd92c365386044c2e8bcd196b3787bfede47fff37
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = a5aa479d792448cc3e2ddfbe444017eea54efca7101651f4616f0260c7a48a364fe459abf98352e86b0b3d1478208687dffde1380d4462fce68cd61895401c3791186f17f159b91c02b5c0a30e894e142657b7537e84d2574837256da6940aa14cded7fbcba24b9e12ed2bb7e3f6db69b5a02807b57c9aa10ad9c0e1bde9443a
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 9a2e5b3ce63cb8df79f3cb25cce6964527e38592c58ba8b7b9312da25c62940985e93e62689f34b60cd019d3d472c0b72fcf2666bfcf8c13407e2150a138caaabaa409e6fd1ea55faf9180f7b41ed53d47c4dcdc3c669928d8a1c161f91918593dc3be3892c8df763d1a5ee6bcd5801866683005d89a2fd6ed3bef581833d922
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = d73829497cddbe41b705faac50e7899fdb5a38bf3a459e536357029e64f8796ba47f4fe96ba5a8b9a4396746e2164f55a25368ddd0b9a5188c7ac3da2d1f742286c3bdee697f9d546a25efcfe53191d743fcc6b47833d993d08804daeca78fb9076c3c017f53e33a90305af06220974d46bf19ed3c9b84edbae98b45a8771258
+S = 175015bda50abe0fa7d39a8353885ca01be3a7e7fcc55045744111362ee1914473a48dc537d956294b9e20a1ef661d58537acdc8de908fa050630fcc272e6d001045e6fdeed2d10531c8603334c2e8db39e73e6d9665ee1343f9e4198302d2201b44e8e8d06b3ef49cee6197582163a8490089ca654c0012fce1ba6511089750
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a4397d9ab677aaa13a68a09de9ae0ed4045d479aa0ff3a7242dca477ab7884faf55cd06ddf19667f668b4589955bfd299dc7642c28a68bb2eba6f08c7ad9f5e96170913270c6463256a0537a72b32a04e5662416ecda74696d275a8bcfe999820ffc2ab210833201332f323828be7dac04c1f01f93a3dde1efe7483a51b1560d
+S = 417aa0531b1da975066a1311a9bf2fa73f5daf90f0473a8937a27a9c6378c53012e0b4db3dcb5309b85a3e7f9db161848465f2e8102f75d171b4dc5371c3dca0bd70626dff5fad68549477fea84db9ac1b405440e178f5d9f74f3935e78a6aaf774b86d509fb25bd1a93aac9a2cdbce6a897842ea3ae07d3c8b4c43f97e0bf75
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414dd1e335f65b2f5e31562a2c74ea6eab09892febcefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = e4690fb08396a8bf07377778a447dbd14c771024bd2353cbbd8446eda42795971c9eda0f2575be655c68614a7cd2fd252569c664dc291410548ec3a5eb06da2078a66c59441cbc9356e5a452f4c0386d6662a663fd6b61f254997ee6d63b5e3080e98d37e873ea737f17083713f7d5ce98ca79ca27d18199470c3d596caf66ed
+S = 56b25cc46a9ef9607f4f0f553265996e22a4552fc6cb2752d0595e887afad29f7f9a390c17dc427c7d9f83f19f6986c60ec6d8f8017c3419cc2a838fe2425c7c80ceebfa1a0a3de507b5601609fe54b871efde685d23e546d69fbd14a30ebc2e67ac99446ae4978f1b3c120103294318b253aa9fcee638907b84ac72b25e18fa
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a050004148031ffbcbd668626dcc49e40128d8abdab1e8172
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 30db68c610b9086e9c6273da708ff8a89d73dfba6e2564aec908292af3a52b84ddd28bbb7c4a39df02f6e992be0d9aa8edb320a6e5a0a001ad097e7b8d09a87f50d55e1d68f47d2215a892221e7e33ddfe181b58fb12c8703e60cf0248c62af8a99111befd96b45ed4cf441a0623b013b94d3dd0976f6b5db7ae595069f21ea5
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 8ed880d91764fdadb04470e04509c6b800fe2bdb1cdb17071f855b8e38b3075c3b8a6991a34ab869127f47a753d7610c79e86a7a288b653326e31d90f4d043f52b7656b6831f6806119df6309a7846b05cb2630c28f7464a7b96e4e8ce76e9cd45502bd5e928f268763fea50271d29b7527097c51ebc2b2a3a83cf22e6b7e3fa
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 4a1716c989580f11bad633a8566b0f44ea689d8bc27c489bbf1a01d76bfa08ce87cace576ade53a5399addee803666fa1d99fa3739c556ae513baa10415e3db820e45f7518e15c7b1875f18f3835792e7ffaed1e7cf9c592afd660d2dda77e00f8f6cf298978929ca017cfce2675afaceca959810a4a33666be9a9a1b2f6523e
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = d73829497cddbe41b705faac50e7899fdb5a38bf3a459e536357029e64f8796ba47f4fe96ba5a8b9a4396746e2164f55a25368ddd0b9a5188c7ac3da2d1f742286c3bdee697f9d546a25efcfe53191d743fcc6b47833d993d08804daeca78fb9076c3c017f53e33a90305af06220974d46bf19ed3c9b84edbae98b45a8771258
+S = 57677b089e205486df4f56755972e3af88cabbc23efe29439b8d1e60ac226e990da487857392856d12cdcea387a269d1bbbc128549a1135ab062201cab8ac08886a313af8554506d7a93855b843086a1bf3dfbcb004ccde779c084ffa1724b41d17e10c8dd67dc0df26200376550eda14455d9b0b31f1d8c5e8bb1d3d963d0d5
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a4397d9ab677aaa13a68a09de9ae0ed4045d479aa0ff3a7242dca477ab7884faf55cd06ddf19667f668b4589955bfd299dc7642c28a68bb2eba6f08c7ad9f5e96170913270c6463256a0537a72b32a04e5662416ecda74696d275a8bcfe999820ffc2ab210833201332f323828be7dac04c1f01f93a3dde1efe7483a51b1560d
+S = 9b2222986b3f97dbdfd7aafd35fba51df5a7b76c88237e7454f2561b542289b424c76ba934e30b00e7726116ddadc359d6ad8b7ed7c16533c5661f2a61c45ec2e590e058663a740c0842e036d59f223d3c87a8127d40024ae205e46e3cd0fa323e01668da8bd723cc17e539a028a5ea69cb1fd9150db571a451ada2d81e05377
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c472fcfddd47f6ba3bb9eb166c248320d9b39fb4b2f70b65a85615244efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = e4690fb08396a8bf07377778a447dbd14c771024bd2353cbbd8446eda42795971c9eda0f2575be655c68614a7cd2fd252569c664dc291410548ec3a5eb06da2078a66c59441cbc9356e5a452f4c0386d6662a663fd6b61f254997ee6d63b5e3080e98d37e873ea737f17083713f7d5ce98ca79ca27d18199470c3d596caf66ed
+S = 7016e23d4fc070a479f4a9c173de8f1dc3a54183ab44af9e3cfda7a229bed269712f5697fdd485f03ea21183f563ee0b5a91d3478c5cc94cf6fb56c0102a7098cbe06a8a5ae6a0eef7722ef9514c80e5944c8b1412b1411d56c7b674650eafca7433ac8b9266363a049f3be30885e30fee049e50ddd76816db309ed59f9b469b
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041ca73d80b7f5f188724498120a21df3683351f77de5eb916058f9769d8
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 10ecd0085694f8db6ea62dab2f239d8a93fcf449102f1368c67de329d79692b677500f55994c9722e2633063fc7d8c2c50ae8857d45c08bfaba9448dda0689c2a08605d47a7694beaacbdad1a954458a87fd78b6519393013b20996d636b755323b4b2b2b6d06a46c9221cd200462428ab5bef0f9743e144191f6928562627a7
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 488d328861653ab0a769a11a158ec7b479b62db5b253eda899beae580afb9a7c762030262b8a066f085185475e17870700504d3f78fcc4bcb95a3c1648796a323613a7b706cb64b048c68c06b396aac20b52f22f3fdce40992fb9a5ef68b5725134d83035a6f091d01aa5947175885822b2d4618c3f3fdbfd8819847fe40112b
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 7c547b350710337c783e7406935fb8ac7bcd1cdd4a7bcaeb63422067d1239f9f59fc29b51993a29d6ac8dcc7980871bbba1be8f0b6ce951a9e0cad64b37d7d0c3734e038efcd4e3499c8855f7c52ea3323ba4876ba9d78a98e7e5cf72b4b7444228dd0d81283e59055873450b8bc411d1cb970efda5cf5947a1d1f17e92a4639
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = d73829497cddbe41b705faac50e7899fdb5a38bf3a459e536357029e64f8796ba47f4fe96ba5a8b9a4396746e2164f55a25368ddd0b9a5188c7ac3da2d1f742286c3bdee697f9d546a25efcfe53191d743fcc6b47833d993d08804daeca78fb9076c3c017f53e33a90305af06220974d46bf19ed3c9b84edbae98b45a8771258
+S = 0b20e5093c2a926233108afbdd851b88eeb554f4beaa7b18e51519f7d0ec53b181a3b03e8484ba8de2aa7864a402e2208e84ec9914af9d776ed13c48bdeb6484254de169318a87c40f2265ff16714eae8aee2bc9c3cb4dee045e4f5d9d625210121bfcf2bed8d3ffa602ce27fff4e61cf9bb650e71a6921ae6ffa296cb11bdbb
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a4397d9ab677aaa13a68a09de9ae0ed4045d479aa0ff3a7242dca477ab7884faf55cd06ddf19667f668b4589955bfd299dc7642c28a68bb2eba6f08c7ad9f5e96170913270c6463256a0537a72b32a04e5662416ecda74696d275a8bcfe999820ffc2ab210833201332f323828be7dac04c1f01f93a3dde1efe7483a51b1560d
+S = 9313380722659eeccf8be943fbf514e90fb19657dfb410a50bdfc0cfb058a58e56bbae71ea1a30ecee08ca5d31a2d0bcd3f5a967a3794259c03635ee24cf2a15303ddb5962ae9747d72e83f630580600ba64d24bc4014c5d44640b2369b45fb09c2ba20721e0ae27d1a32546afa1bd023aa61079cea65389f55c31cfedb460b3
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420fa98b3853b928263002bcb39b454ea21f3f62bcaf6bc2b616490b7a7160120d7efefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = e4690fb08396a8bf07377778a447dbd14c771024bd2353cbbd8446eda42795971c9eda0f2575be655c68614a7cd2fd252569c664dc291410548ec3a5eb06da2078a66c59441cbc9356e5a452f4c0386d6662a663fd6b61f254997ee6d63b5e3080e98d37e873ea737f17083713f7d5ce98ca79ca27d18199470c3d596caf66ed
+S = 477a7d6ff281bee7d56ac9cdc7f041b7497483f07a3cea5667ff178233219f75da7b88d9fc854a22ef541af3a5be8fb30b4e50bcb6d130e11f6c18eadec5d10f9895d654c0947aad152ba395c1039d7a8ff41b829179984a513f1abeb5a748bf248af1ea0152093d9fafb5d18e4cf91bd3b57ddd18b6984d976e6bef58cb30ec
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d06096086480165030402010500042034c9d0b0b487446c903244e640affe835096c7ada2e4295090bd9386884df006
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 5ad712eea6e12cf093b8aaa41bd972bd92ea43442dfae0671b27b80d821fdf8a83b032b870e2aa618430ab207ccb1c86bc5e74ea44a0f1ba2cfa2fca003e8547eedc4fd748e7718a9dc39c032b9bb997b4c01f49e441ddcb134d9b2c28a3dcbf126de439f07cb58aece617573797d939957083e51fe5eec00deaae17c41f59ed
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 1f00ccb2e22d0355b20b79b3d3c2416c03d281673fa3314aeec0cb41373e9a8ad5441e93545b6ceb9d3b8d660709cc2b8cff61924768fcf5b0d0ac771a395c02797123f503866d2aee5bb03c651091388486f63793bd714485ead5e03b92c9d80668c2088866b14361d2eb5eb838f903994d84471d5a352366eff2c5cbdf1ab6
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 52edcc1c2bd6eecfda613f0ed8cc8ed5d0f0b881b5a05eca36d9fbb3d04a9f36f0fa916008d13ae8b17b8f6d97ac4450d892b2731f14a477032cd353b8c054d53a3b2932124fd8d1bac88b44e4fd6f37b8ec3575b290fad24a262011b45f7e9b96b09324901f1d153921e13f7246ffdce405018c20975dcd28a7fe55689bdd9f
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = d73829497cddbe41b705faac50e7899fdb5a38bf3a459e536357029e64f8796ba47f4fe96ba5a8b9a4396746e2164f55a25368ddd0b9a5188c7ac3da2d1f742286c3bdee697f9d546a25efcfe53191d743fcc6b47833d993d08804daeca78fb9076c3c017f53e33a90305af06220974d46bf19ed3c9b84edbae98b45a8771258
+S = 7e3ccb6ab03b419a3e54f81337a3c3f72e8c65bbd19ddd50246a36f51f58741ec245d2d0f07677a4f88aa3b1caeecdffe5fd6edcf8b8bcfb569637ad02eb154d17b87a8f00d0e618a7f4a70ce407f20359153e5f4a4d9744f3f3ff44120c08a460500f030fd3398e97fcaef9d0a7e2acef19a81f706805be5fc003d78e5b29c0
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a4397d9ab677aaa13a68a09de9ae0ed4045d479aa0ff3a7242dca477ab7884faf55cd06ddf19667f668b4589955bfd299dc7642c28a68bb2eba6f08c7ad9f5e96170913270c6463256a0537a72b32a04e5662416ecda74696d275a8bcfe999820ffc2ab210833201332f323828be7dac04c1f01f93a3dde1efe7483a51b1560d
+S = 1077cf5852f21c7986f30bc2bb382138e93c0670315a83799047e122b7804cb8cdc892f23c8297b8315c16c351f0c6138cecb630a51b8a0980eeb59d575b3d86c52ae9270c6f444143d22ad6a1eea05a886281c9d7c93f0d3ab2528bb72e99b2afbf74f04038c3e17743e286a409304e4c19d441a68142b0d7b3c0a6da5532bd
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d0609608648016503040202050004301cdb4de69f4d84845bef51cd666020a895fbea98f2f61c9554ebdcffa525877093cbc9a4b1b8efeb77980d73ca54de17efef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = e4690fb08396a8bf07377778a447dbd14c771024bd2353cbbd8446eda42795971c9eda0f2575be655c68614a7cd2fd252569c664dc291410548ec3a5eb06da2078a66c59441cbc9356e5a452f4c0386d6662a663fd6b61f254997ee6d63b5e3080e98d37e873ea737f17083713f7d5ce98ca79ca27d18199470c3d596caf66ed
+S = 63c488bdf2f7de4cd048c535b481a4cc2898e3810eda0038b2283bfe9b3f2beba2a74268639ecfc05170d1af534ced5d3b4941d1aad317875e05d6a19f734625721ed1f262faf995feb1acb44ba76beaec957aa8023429865717d0abfc553cb67474034344ceb8c5d4bddff7fa230ac620e5e665006dffb1c4cc7995c73841f9
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430cf563bb8f42149df04c9bf20652986e8888907d2ff11f086bb1b6152abd4e945ad82dda241cfbf511a88b36a5a450dcc
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 48db9934d51e8c2e234d70ff665bf2de4fef620e23f27550254a0b4b18338e299c024c4ffc5a502945e9f2e091a86ff6e7f44059f1ca58b4a18bc15931ae1176a9775247039e57d4e322f3d77fed6c6e9bec26b066fe565384c42d2ac79dd8312c8e09d3a2bf85fba0648a02f0e958d4711396e42362c5558eb7227b12aa94d7
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 125b4dddf5e18c8de2f7b72faa76f1d03dd88aac3c76ebc037b4b1aa1435eda6bef2c948e2ba51e763b8572f4ecef228ca38c10299add6f3f67c171a8fd56e33a1c287c49f844e4e98b20f0fe727b58515e5e7d3846c029afe08d25a9edf0dda6677b1cb2ca6be67763171f114932c43f53af126d0aab6dcb52d5b320b385c6d
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 70a4fc2afc2524ec159aaaac0cf5242e276057c3ebaee9c3c430aa862ac5758aa3a55f6f6ebbb25bc5229e51c976949314244efb35d89d4516845e41f9cb9c4db78d381eb35f257d3b9981eac9e27cd9d18a56a6dceceebb77523255684ad6ff58622889e08a616acafca687e2742074d0f7431ff5ca4324c4d25b44af9fd2aa
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = d73829497cddbe41b705faac50e7899fdb5a38bf3a459e536357029e64f8796ba47f4fe96ba5a8b9a4396746e2164f55a25368ddd0b9a5188c7ac3da2d1f742286c3bdee697f9d546a25efcfe53191d743fcc6b47833d993d08804daeca78fb9076c3c017f53e33a90305af06220974d46bf19ed3c9b84edbae98b45a8771258
+S = 8b57a6f91606ba4813b83536581eb15d72875dcbb0a514b4c03b6df8f202fa8556e4002122bedaf26eaa107ece4860752379ec8baa64f40098be92a4214b69e98b24ae1cc4d2f457cff4f405a82ef94c5f8dfaadd3078d7a9224887db86c3218bf53c9779ed09895b2cfb84f1fad2e5b1f8e4b209c5785b9ce332cd41356c171
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = a4397d9ab677aaa13a68a09de9ae0ed4045d479aa0ff3a7242dca477ab7884faf55cd06ddf19667f668b4589955bfd299dc7642c28a68bb2eba6f08c7ad9f5e96170913270c6463256a0537a72b32a04e5662416ecda74696d275a8bcfe999820ffc2ab210833201332f323828be7dac04c1f01f93a3dde1efe7483a51b1560d
+S = 8e0fecaaf7911ccadb8ca5b6ae3bb89580cbda49d3181d5aab4f03431c62aedb4affc58b87c4b3c4ee09f7908f34f52e2901891382b57cd78d3a824fe446eef4ef46b2afb0d34e6cd9a263c21db8c9c2cdcd5e60eaac571d67410c7136180ddd6195ff2a0691746e457da69bd1667a56b1980a22d5f0b3595af0e8c3bf97c2d6
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d0609608648016503040203050004406bb51b0f43cc58788c9d60f71e06fc473949ae313b3354033526cdfac71690c584f916b1a8eeb47f17f339b6cccc3fb3a53786d418295c1e454db8cb17cb7de6efefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1c23c1cce034ba598f8fd2b7af37f1d30b090f7362aee68e5187adae49b9955c729f24a863b7a38d6e3c748e2972f6d940b7ba89043a2d6c2100256a1cf0f56a8cd35fc6ee205244876642f6f9c3820a3d9d2c8921df7d82aaadcaf2d7334d398931ddbba553190b3a416099f3aa07fd5b26214645a828419e122cfb857ad73b
+Msg = e4690fb08396a8bf07377778a447dbd14c771024bd2353cbbd8446eda42795971c9eda0f2575be655c68614a7cd2fd252569c664dc291410548ec3a5eb06da2078a66c59441cbc9356e5a452f4c0386d6662a663fd6b61f254997ee6d63b5e3080e98d37e873ea737f17083713f7d5ce98ca79ca27d18199470c3d596caf66ed
+S = 9572ebe453e2f17dd72921b38a27c28c68f4605aedf6b4a7d54079e3ceb2811ccaa6dbc0d71d47d93cd1f18cfb028744fe3d8971b0e9712f29ccab4152e2635dff3b9a1e9cb8f462b138b00c4c0a1163739286b50ac232da5075a9ba3c02a3f604d4629a7df516b39c8d01cb5019f9630436c70415c6b16d79bb29f3a46b72d6
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d060960864801650304020305000440605b7b97abce7dee5f9b9ebf2ebe35d7e474e62b3a6e86b108cbfe3c3a8300bd11deb0210048f502b7af1c9dcb1805f1d61e8df038359729a4bb33774b9d13aa
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+n = a8d68acd413c5e195d5ef04e1b4faaf242365cb450196755e92e1215ba59802aafbadbf2564dd550956abb54f8b1c917844e5f36195d1088c600e07cada5c080ede679f50b3de32cf4026e514542495c54b1903768791aae9e36f082cd38e941ada89baecada61ab0dd37ad536bcb0a0946271594836e92ab5517301d45176b5
+
+p = c107a2fe924b76e206cb9bc4af2ab7008547c00846bf6d0680b3eac3ebcbd0c7fd7a54c2b9899b08f80cde1d3691eaaa2816b1eb11822d6be7beaf4e30977c49
+
+q = dfea984ce4307eafc0d140c2bb82861e5dbac4f8567cbc981d70440dd639492079031486315e305eb83e591c4a2e96064966f7c894c3ca351925b5ce82d8ef0d
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 3c9db203bbb31c7a3498b3b35ec2ea818614f3a17cad8308f834c6945305e3b94f9886c00098640cb56cefbf06a9ebb7a8c28af610c49896dae53303fb716bc3d2ebf95205944f845658732e8a7ee032472942292f82ba24a66094c7c3b417f5e678a19c04e3b54ba5f0f03610c56d31b9726ee0e39cb1708d89fa61ba9a039b
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 6592c64db5ce133e1c7d499bf7ea4d0203897186b4319fc5e29522d97b9af212fd5a10a8c15246a46d0382cc61c9bfe2b211871d7dfa4eff9a6fa15426309844fa72b1de7aba231c66076185014b9f9e9fadbc2a739ee95c48da75fbfc7d05c22e7896db47407e8d78f0d28519c7fcb6c868b05016bcf73075477a92e97625bc
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 6c80cc0f17783b39712a994f16a461830c26ba3f3afd1a277cda564c8a8b41c4ab444bb6f79df1d109f781de3e6e81d2a0aa2b6ff566e065b3125a6bebd36039aaab46e38a3fb36f66e665372f0cbe15a696d00cd79922bce7e6771ac59fa0c4576f28eeffca9177bdfb0804d2f883b929f58d4ea948df8bb3c283fa337d5665
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 4ff6c9e7f9f03abd3e114a788fd51318feda52b6509c1b685483cb6574213f6a8ab4435cf5f34d2eeb076c0510d77b9a48889ae0ca44dfe8773b480169e8f423ce96938ef7221caeac02be42c38618bdf15eacecdf5d91da807d69f1a3229361c4a3a2c628060d05290b2776ce6d52499e647022b66e9b071a4f167c495683ec
+S = 6466b9759635fbb2a3e8cb7d2a6192ea7da6033b76dd578b76ca468fcb9215f8138966f9aaa3e82246d15bb271a269eda087e63812406407ca12cb085ae82ceebcf28eb44f6608549fbf6383882c864688665a1b5a2d748496b36f8b935f676339fc61e9bc0c3a5a58141226f300cf29c4371047d530a4776809f572b88ecdfe
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 85624c37ee13b3d8cb80a5961a39c5953caf10f1b4e9c00a2c78701fb8ac821f5f08bebbd8f43bc091b283a4f693f25eef6b5f7baa42ff6f9c4c8529c21c8eea2d143d56bd2022cc2da461f34fb210959981e0b1e11a00cb65553e870e047076f66e123027ff30a3a63d87aab0fee7e243d8dbb9e0da8cc79079e36225cdee6c
+S = 705a07d366f2326ced17374d5f599d483ccf184d5fbbc288face464b64c058e6583b8ba664f979f3a6c1b0755b1e2cfe8154c39176d432f59af5714bcf9b0af8da122af77f0393385613393d43db7902eb1b81fc9dc6604692e0f85d30ec59fdc521cd35e5aeef006a6b919bdf47bc9a468daf3e86b3e4956ff736bbc25c9ed1
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a050004143dee53379c3e2d8c26a41c9f63be60b1993097d7efefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 263da806fe0a7a242843f295893fd891cd13c0ecc1648c90fc79322bc594bf2531839cd58c7210f4fa0307525ea112c77b11ae6d5a49c90ceb8682d6ee9931551481a7a1623fb7d6d7e6f5c54ef2bdeaa6da779f1fe91a8e0749ef6c976198e5186150d2491a74b20514435821dae2e19499a2e9dae986ff9aeb00558694fcbc
+S = 727d32d7faa37ab2dac96e9f822be4dfe60459ab7aa18a26cecf6c84bfa7fac7261c86f89ca84356ee20fa9e8a8a9a2b5f5e624cc4269aa8583fb148777091ecab8929e3f8a628c8f6e1b3a48ff1f60ce1b40f279439bf8eadc6c1b977b51e8ec3c65cb8db9fdb956b514d28381260b9f6b02b2d065ef57770952d968bed65b8
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414eaf16b6fc483cd5d255ffe76f761420c4df301e6
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 64c3e9ef2af3501ed929ec204d43848d42f3393e437b4267c70d87fc5296ebd752739088529c16e2f6f0aa87e1bc6843779dac3af54f90d3334d4b65b6b0adaf91b6fa8a75826a30f50177f887e705fb64a9258f131dc958bff8134bd68206b9d3a6fa70b2c7de5308269a6c33716916c37810aa69ce3e81db88674a07fe55e1
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 6c9e4455899b0ede371ddb6fe074217d330fe0e27537b0f06ea2e24c75ed6017594ead552296da15f11e6e6923639d95fb73e98d5160e80754ec12f4a06660c6e27eb4de4fbcfbeb37176ef5281a190249e34276a2d736e622c8151f3d5b838e450383edc986cee6b00a1d4cd5a7de8fc8629b6557a3becad84cff5c6c51f2a8
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 9edf5246ae1d8fe800bc2ed422e6441cedde94c85a870277972a4b4a5a74f4fd76be8057ac92e6c5c36a4242dabacb79fe31052ef83c38da68cd2095185ae6398a284fc5d3c934fface4325ec734a2265fd3cbd513b957bef47f04f4dd699c6903a42757cccc5fdfe5b264f18f5bb16b394c4f855404486c63cb5f2d51aafed5
+S = 9b689f488edb16d4aa3192af3760977401dd066d319d4c5dacff4dbe8aab9aa5790f39bc2378d0c8f52f286fc1cabb743bf6aabffacf5ffe4186054d0b121a2e6559806886759398e7d30781380aead8af992485e2bd582208dcf69ae8e7124b1571cdfb7db87cd565f293cb8d26a8d005508a3332d4ec27d44a1423402e6d8c
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 4ff6c9e7f9f03abd3e114a788fd51318feda52b6509c1b685483cb6574213f6a8ab4435cf5f34d2eeb076c0510d77b9a48889ae0ca44dfe8773b480169e8f423ce96938ef7221caeac02be42c38618bdf15eacecdf5d91da807d69f1a3229361c4a3a2c628060d05290b2776ce6d52499e647022b66e9b071a4f167c495683ec
+S = 86ff99daaee2a3c866a71f7f6fb391b9b31a3cbcf525321087a6b253e42a7b5fa386ba3907751933cd153431507b78486d5d43dd35779962fbc9babc487afc696b0140ade1456fc5b23ce5c7c97019247e827cc7032c7e101b68eb4bfb003ba107f042b92ff697789fe43018d28794c7aa8a70a5386e891e3456a5e52990853b
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 85624c37ee13b3d8cb80a5961a39c5953caf10f1b4e9c00a2c78701fb8ac821f5f08bebbd8f43bc091b283a4f693f25eef6b5f7baa42ff6f9c4c8529c21c8eea2d143d56bd2022cc2da461f34fb210959981e0b1e11a00cb65553e870e047076f66e123027ff30a3a63d87aab0fee7e243d8dbb9e0da8cc79079e36225cdee6c
+S = 1f4e56f13d4167951a716dc8340c006715a4b9340a1bbcfcbb7befd70e15723d81ee5152c42967ac479b3a4ceaf1527b9379daeb245c423a21bf35826dc0f6b90a4caa579d962023e12e2eda516484ddc9483b91c7853d03a1854536d1e6fdfb9217223d2d9132a56d411183fc30de2463c4d5bea4429e7599dc9c4dd2b96b89
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041cc53cbccde35eed66e504f5ae6ecf78ba8f83abd4b67822b40e121f99efefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 263da806fe0a7a242843f295893fd891cd13c0ecc1648c90fc79322bc594bf2531839cd58c7210f4fa0307525ea112c77b11ae6d5a49c90ceb8682d6ee9931551481a7a1623fb7d6d7e6f5c54ef2bdeaa6da779f1fe91a8e0749ef6c976198e5186150d2491a74b20514435821dae2e19499a2e9dae986ff9aeb00558694fcbc
+S = 002e26f1d72dcaaf2935f4177601e7b55da3ba0769372a2326d4e621449deecf84c2b3b2998da662907d167a6e7dd0b63116acd7c98d3e086da986ce126568aa31ffa136efaab815ccb9e8059a1e2bf1393dfe8567b73c8191d5acb8560a69514495a33362e05b94c3e260e181603a5d5d9a589c21c5b18effbbf016cd493276
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041cd8eee327931d42ecd0654f1da8d551ebc5ca117b9a9bee9d28049ac5
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = ff23e00f819bae424e41d6b762ea6b88801e651c831c964af31de0c1d6dda4a7c8587d804ed12f526819da06650e7412fb627555979ed442f2663341e5fe57527e0ddaf453a124451674976a6a6e0a31f56a79f5b73dfac39af4f3ba4a5e8bb846cb5e333812756482d975ab1910162f96bfd7c58a02f113125189f5ac05291f
+S = 8b5a3675f397841c53a9021dad71a1efab91451c71ad7060ce85d75b306d6403ba23d3370b0695be87485cf6680204c68424bc7e442ef90ac01c4df420ef574294823250a000d56a5d00947800dcb2f4947f5b4eb18fa1dbdc6ab16be4b7131102d4dff98ddeac38554473964d29cdc521ee690cde5a8cd16889aa090c32c53e
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = a6ce108ff3100b953781496c3d081fe32b8cedaf6d14aab2ef2dc37d8f8d2613d2f599efd55c51498749c0961681ae4ea7e28bf14a8f044c2d4dd4f9102ddd25f86c7795289708eb4df2d526f91b176952eb52fd0c9de2989432d6e08e13022b82f95089d20a5704f0452f26cd1f83bc956ee7da99876c1f8da3723af388bead
+S = 750e59f29d2dfeedab2a3a09034904715957149126c63e6a2dc7a633a32c4c0561d54eeb1479cb65274bac37cac4751f4dffdfb7530171599b61d94862845f6cd12a5e0bd6adabc36f06d216a00b1942349710540555106aeb87f5cf3f78df918f36cf63291ef2a7064e31b84075d1c8b551225a25f59c721a3d77046078557f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 9be28a4763c6665880c1c2a8a74494622be46de3c20e5b118cf70fee51d33b6d0b473e84a4200382004526a33eea59e13b07070e580937207ec7b2cc5fb76856fe6210a771150fa0e5da9baee4a6209ed3d4e2b3bfd2e5f6591b0ace3e657ad07c1b47d8520d5159386767f11fdfaf41fa3348fb7dd32d3c25da5d1d78433985
+S = 0ac6e41252383ee5d07f4fb08a22204f56440a8f3c8568d6e6bae46cfc9d39b65b2eae827164d716e9e465301d08fca7356ef447e0699feabbfac16ed19dc9233b457fe64d6fab38aca4464e5cd3eae3f43bab17856cdcc942e2cc848b7bf390fc53b3ed2e6f63c5d961bc83475ac200708f6e1d5be30cbe24fe4d3dad754269
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = f56379c42e3ba856585ca28f7fb768f65d273a5fc546156142857b0afb7c72d2d97ecfceec71b4260bdc58c9bb42065f53af69805d9006233ec70a591aff463bf23d78200fb8cc14a4eba286afe8924120efad9e3d3f06f7452c725e53728b8f86c9fb245fbaf7086ab0092e215213830d1091212efc1ec59ddc3a83707d4ab8
+S = 5f49d8dc4519d9520d6542eca08cafb2d99cdb97c5a8685df2476b40505a2f9e8d63d76516b83481e2d961a7e8dc5f9f46887e394776711b0f85e4303065c06d362456bc219fc6eb343ede6733f779f75853533bc9ab876188da8ad98f9ea2f335d2ceec34ef9cb2782bb0f79cad309608ddc222e00ebcff9d14f6e6ed39638b
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 399b54f756514628f32ce8f1cf391d77047af55f3d43804923e5e09a188aa27f28604f2f3cfa3d7091f3ab5c69d40d650137a597c22d531dbbdeae074f6f534a2b297e087cd7d7125e6f8eac97f5a990859d9d3555301c5076b02f9c4d3f84d62b3d090c7cb1ba1841eab668c066990079f206c15d1383eb3ba58ae17bc2dc2c
+S = a62e4b688bb3c4c2e11a3a0b1ef81ff4bbaa110c9b830d02bda2d364dadb2345a8c5dca58c611515f0c09732ee6a6642d5c5c339460a9d15022f48c36e9bc2fb8b2b0ff99005273287b8c3bed87993baf52f0e9d079281bc25a8694ed9692446127c26c34f21e610a84f3617247ecfb3b5337fe59d1239dfb7fdac8694dbef0b
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420be1f73a059cec568dcdfddf1daff4201e79273653f88ef8f16be7e9ee660335aefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = b8518b80a55b365eb1850e18f88da2941c99543c2f865df3d37d114d9fc764ffc5e2ae94f2d4ab6276bfc6bda5b6976a7dcfaa56897982880410dd5542af3ad34c469990cbec828327764842ef488f767c6b0c8cd1e08caec63438f2665517d195a4d4daf64bc2a70bd11d119eec93a060960245d162844c5f11a98cd26003e1
+S = 06317d3df0fa7ae350729ae2096b050dcec8909d36681ccca09a7a527b90767f8c2318c49e09483b48df77ddb632d6ca721155165389f7795d3ede70465678649399242aed6d984ca74fc6c2eb4dd4bb2cd7bf2125ec853f2bf757d665b29487bc5b63df0d0b03b18608d3d9a7576ea0954aef3d3303f7d8fd7e7f9725c114e2
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420a51c139e5ff91509eb0bd542bebfb9a4baa9399a5535d9168942298ce69c4f5b
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 678507d9ebb2c5254ff371d3e41b435deb1118bf0b0121c1bb8a46575df101d12d771471b956f8c229b8021a9f08faa61e0577c6a715108874bf655576954a85fb63817b58298fe3d3643a748dcc635210d2b202e3b2e663c4a212ecbc7fdf5e34e8d499a20034d98732c09be015ea728d1cc831c61965f3e32a8aae958d43d7
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 8d26faa1cc87606514e47b7ab3d82768868a61d237cf18e75f935e20fc5925e2c667b05cbd09da878fd623430f71ecd1f632fff4d1d049ae704004c89012008e8856f61a03001b423f4f06eadb4a72eb946a7a4dc4469e995609801498bb7471a533ee0f422adc5d41b744301efd836e5cfcc496cfc6ee646ae2218e924f76f9
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = be9b41883cfadec3960d866fe8514f9821c6c7e65af6e5c167343fb8ac227e2432760f08fbfd1c3c92e0bbcbe5266599577aa949122e215d9a81a69fa81dc0c035e46040d5ecd28d46c8ed6f490a8da3b00543c7b9d84a769aa8bdb35d2c088bee6f9df673d1e8ffdb4f8424ba05af0054f1fb27f7fa47528f31eebc74563ecb
+S = 735c47985ee75db358eb0d05624be43778a37d40ad1df88cfc5b4669906e290704265fb3a133df781dfdfaa082d21d0c431b54c0c6c239fb0c0b47e675c0def6d94a726ff8267c449f1300b21a7c7f171c76e869851f9be39546e274f60924ddeedd4f69b70d97293a10ebbb3df8f9c1fec31f7d3562150a357150fbc8ae5237
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = f8a2f38109c9b6d868c5b3481cd3478c8e0845fc3e36479cb50f4158bb8d5c8ec99101cdc1ca33ddddd823ffe5b1fe75a6440a459f5df13bfdc95d2dcabac482616d86f52509359772cb3313d46083367792d9afdf27f313d9062c24b29c4f52a67ea9829b50620f10e50d0e50a77dd7eb3adac1665cf52c3210d9c5dbfba305
+S = 9ebce94bb79d82fcd236874df4c2c3d1b56481ba15fc17a345f6d45297b6adb9e07c1b582e22ce0b1830763758827a77ca675c708163cbe7a5db72d2a95939b3cef60c632a19849e6d95bf6a867604eea7f69b506bcee7d04678d4252c715edf0a928ef4c1181177bff20c3a95215782cd6b70564cf1ec2ea25e6318ef1f96b5
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430940085d291d91da907231dd6d6e10d71011dc3e0944671e632bb0d87c0b8fa1bc2f1019caa64a8f6844a8db073b0743b
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 7e3c652fb2786a379614fc8f9f01555cf029cf61cf0af6c455a4e2156996c48cef84be923cbbf883cd18f0b3392611af658688c5f79453c60d479a0a2e5943b581a8c1393cdd2c1c604b97fca41a9ed0aea43e70891fea58547ddaa83790a7709c72152b9b242f89b5759a72c6252347354b9a6b6ef4e302920d4af86c831745
+S = 995e2522f280d28f9719663178429d6ffb26cfcfbcc15812e83821db1a5e2a31a8160574e4fe4f1f09ce67690c67fe89c11015ffbf5dd5ec669561f0a2b13c416992de570a532b805b00b8003f6c70d56925ff2bb5555daf3edef1da6bcb1c94d29bbb243119da64ef352d36ddd6ac472a99a1a22da809aa235b51afc8379619
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430cfd23d0f765da0ba39f284a77f62552300460944a69e6fddf7aaa731f62c6d822f5eb581075a23fd540aa7a920f7c3bbefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 2bd0f6349c6f8198a10ce8e761feb6d4d72bc71addcefc628a773367be537758fbad737e77b52d1e6f80f1a1bd518af2ad17b9280d36df65838afdfd24a9dedb4169932184a3200f3c367526f64ea08d4de640b3038b3d365063b604796f3bc0a50d3d67edc1c233b2345dbf337d5e6d5ea04605e7547e9e980a48c2e82af5cd
+S = 38103ad73f8bb3a9c3e01e95b8cc45e982a64f17a318026e185d523dec851ef9fbd1b9c2694a4688925580bb50709ea624417a685b39b36e988d9b7b41282cb969379c3e739c0a98151db9181dfa58c5e6ffbaaa6971dd5171d9ebcf18ce346364f7601856aa68584ee3303e8a69d0dad778e4a4ba3ed4f8a009d561652d134e
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 22754363656ce107c1beea8999cb4a95d267d6c6d3a06b42c939f51254f822cf49bd6d51e27af51afa0d260fb4bf6fcb8b4926270851d64f2fae6f4c6562c532e3fd72db5188c51eb57b01a871004b38d6a1bb4856fdd93573735a480b4c3e444262d198d54de6db409db7432dd45beabc34991cb6868e1e1dc62f8ef509f36e
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 92cd8a854b4b9842c12c7f9ec2dcfad57d1f403ce8276d355f436c1d9aaa720867dc5a96b91debceedf55eea2a33d99e586a0a59d68e9289ce6f001be3d9ae9887d9f169ecd77600ef60b97851bc8ad6c5566c830a25690a13a92bd082fdc0b356a6443fcae3d29c5e9818b06c69748149a3f34793a6c7b04da345caa01d6f20
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = be9b41883cfadec3960d866fe8514f9821c6c7e65af6e5c167343fb8ac227e2432760f08fbfd1c3c92e0bbcbe5266599577aa949122e215d9a81a69fa81dc0c035e46040d5ecd28d46c8ed6f490a8da3b00543c7b9d84a769aa8bdb35d2c088bee6f9df673d1e8ffdb4f8424ba05af0054f1fb27f7fa47528f31eebc74563ecb
+S = 5d8ce84e9473178a2ab5373d3154e7d649b40a144040d4a612e9ae43666d681458b5d985f5bb1bd5709455f5421dcff12307e074714b6592f0095c0a67f66f950ac8e2cc7b8ffa5d8f89d407292ac659a4e479ee2cba19d6f31673edbecb3535b85b11edfcea4df17799418fdfda145711f5f9c0540f811ac92e05bea4460c87
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = f8a2f38109c9b6d868c5b3481cd3478c8e0845fc3e36479cb50f4158bb8d5c8ec99101cdc1ca33ddddd823ffe5b1fe75a6440a459f5df13bfdc95d2dcabac482616d86f52509359772cb3313d46083367792d9afdf27f313d9062c24b29c4f52a67ea9829b50620f10e50d0e50a77dd7eb3adac1665cf52c3210d9c5dbfba305
+S = 3c42cf56c04c1ddd18a5ec523df036428d09bb44a7b12be5bf6fdb3866a122a5cd0edb2cc81930c126a9244afcf6a27c8820369f474a06f8b7022ac8b95e35791a49d71a40ecd145e8d2e334b15f6ed698b7a646248ee73f567739469960c0da5112916a12f212d198a6f6c518b4745a578d265ab1c04438d7a38263a5a8c254
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d060960864801650304020305000440174762fdf1f011f716417beb00598a33aae32c141c664908178740f19833d9109154e89f80a1ff369930cb2dbeeba511433122236e0cf6df2d7b7202de550c6a
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 7e3c652fb2786a379614fc8f9f01555cf029cf61cf0af6c455a4e2156996c48cef84be923cbbf883cd18f0b3392611af658688c5f79453c60d479a0a2e5943b581a8c1393cdd2c1c604b97fca41a9ed0aea43e70891fea58547ddaa83790a7709c72152b9b242f89b5759a72c6252347354b9a6b6ef4e302920d4af86c831745
+S = a6825908039d9165b1f1d7e85de390819b3e13fb914521bde6370db313e0c37444bc1bca1d798a73e9602b3c61a67b6c3531c25a0528f4945ac7f27ed5848b782668cad8533000a42a0435de4436e4ee7fe0f9a347750543d921a313c6872cbcf5466ae41a69f32d03acff357cf3e4f1a3e7ed4575dc61bf4fb77a04b9d3cb32
+SaltVal = 00
+EM with hash moved = 0001ffffffffffff003051300d06096086480165030402030500044062eeafda47b660f230159a79e8b20ffc84752ef5ddc420ac6478511cc199f983ea3cb8cbeb9955c175ba5afce719ae601c6303a1f6cd5e0c241b5cfb8577deb6efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 252c4956ac328ba04789bfdc5e90819981a100f3b540069ba8719b8b3ba27980cc7c96710a75ec0da83c1ddf353b45845f3db7224cdecbe5653cebb01fb66305d42e617e8a51514c6d2fb6b3cbe3ad9478ab7acb575f854ec9c9576a70c63934921c39662b32b8c93fb660f64f50e5481892a8ef4b92a64774995f2a0fbd64b9
+Msg = 2bd0f6349c6f8198a10ce8e761feb6d4d72bc71addcefc628a773367be537758fbad737e77b52d1e6f80f1a1bd518af2ad17b9280d36df65838afdfd24a9dedb4169932184a3200f3c367526f64ea08d4de640b3038b3d365063b604796f3bc0a50d3d67edc1c233b2345dbf337d5e6d5ea04605e7547e9e980a48c2e82af5cd
+S = a5c713d065e204f5a3d87e4752b235fa79a703931065aaf7ae4a29d641763d7ea4350d8d9a29b29b4fc770169ba7adf1cf7ba872769265cab2d41ee7e227e7682c749fbc5836debc02485eaca9637391c3793b3f05701f80a90cfcc04c091fa37628e4eebbefe5ceec0b4dee1b41241fb883252fe18ca65ab01e4a4e3f31ba36
+SaltVal = 00
+Result = P
+
+n = a8d68acd413c5e195d5ef04e1b4faaf242365cb450196755e92e1215ba59802aafbadbf2564dd550956abb54f8b1c917844e5f36195d1088c600e07cada5c080ede679f50b3de32cf4026e514542495c54b1903768791aae9e36f082cd38e941ada89baecada61ab0dd37ad536bcb0a0946271594836e92ab5517301d45176b5
+
+p = c107a2fe924b76e206cb9bc4af2ab7008547c00846bf6d0680b3eac3ebcbd0c7fd7a54c2b9899b08f80cde1d3691eaaa2816b1eb11822d6be7beaf4e30977c49
+
+q = dfea984ce4307eafc0d140c2bb82861e5dbac4f8567cbc981d70440dd639492079031486315e305eb83e591c4a2e96064966f7c894c3ca351925b5ce82d8ef0d
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 4bae63c2b4ed42b92d95293ba755c0f3dbae5a13369b298147e3d7d9cf8629b7df9df22f13370239ef86c91a6b15efc5611057b375e948d554a95a7119f5663b0ba6c373121f2d4f6f9a8703a78153be3472f296254db218a22925546340dd0495ec68f354ed17ed4f9d85d4b9eb1b9d1816cc1422c852410841f166e69cc212
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 8a8b25a74adf17dbc6ee3dba1982f94c17ecae57a75835cc4cd476a1afb23d01c964e8532a6d0afe71ebd8d26a2e5514906caae8b18ddd860ae16303723cbd0a155cca1a4a7be32c2396b1d09544057e7f7fdf6bf1bb2861ecc0f90223269add410dd66ea54a507a31b75528bb277ee9d3d3096d2e2f0f33b0509f27bd990b9c
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = eb2a75ef219b2bec0987c2623a76a8d3c292754519c47f8d541aa8cd9b6c7b3cdd3f7825c2e9ab33e2f684eb34cbe27ac98971b1ba34364e5f15687dc15c829e520a9649dc0ee48fb8aeab8340293ffa869b5c8e4720bae91a3ce140ed7b3f1db25478625653fd8bf378e03346dae7d9638fdfe5a7d032e6ef59bc1e070fdb40
+S = 0fd7069ca1e24f81f3c67b0bcba5fa72764655739d549a59288e6eaebf4d2f52c52eaa17e495ec2b2fcb52a4673aac2e48e2078688b8e5d8a91d7c8c4bae725070425a183e95b352999ab2b49adce63b6c9d48dc29e0649d91b73fb04c45786239b0022231e5e173e2f0d94fee7905706f39ec88fce30d107e4151d010be719b
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = f1cf2ba2463023a1d329957cf3fdc044ffecf8ce0a11f9b6ce8b7ba5e5db07d03d8d08c1c61b255a6d0ece174e661593253cc04e06a69cad4fdb1442da97014e77c1c484994c93104f5b10d876a820022e26fab68ae57e258c36c9ca501106ef87b38674278b14cc61578248d48b889800f2cf8ffd9748266ce6c2c4af0fbcbc
+S = 2e305057388fc454647e2c20b71c3cc3383af683126b1b802b6e74096b46655df2715e18bbd1f9f7f4484dc63ea58bd7461c58d6e7ed63e885a2524b01eeea2b9d0cbe25e6f0f780fed9fc9610ea5b7de468b0cc409da4607a367b2815d346facdb6375a7723d013f2d8726e7b40a680b82c112324ab161aab860a943d4fc84d
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a050004141bd3d18838d09a61c2b0ba9865a146b958c0ec0b
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 8b61c39efa507e17cf4d575bd600286d56a40e84f35d6c06d3cc33b400e161220df1c86bfd0911226081008cbfd4fa0c3aafc4de70478d089ff02f8e0cecb2e6a68011abe64d4196f9de70a9217e8bad594c02df3891cfe71750b509761fc59f9c3627c77ec61759e28c2e1cc4a5e339f9a451ef12e23b8983154d8d0524a437
+S = 72c3377e5a389a176383ffb832de6eaf3b7ee9dfb38f504031af6f3d059cd9c1027e22233d1ed0908bc08ae5edb9aa491aa189610b353b31ec92eb8186c0d2bbe8fb1364c3df8393b5917f69243ccc7cf95edd413cc175793c964efc3eed10b6c2c4de4d7b75f419a68e6cf8eb1a09b0ff29c40b713ed63c4fcc08fb59ddfcf4
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a050004141c6c02fb4af79739cab2f59451c9ec6ff577051befefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = a6cc1c55dd9b8da73acc6716344503690a9db27bb439518719b41da28284c9894fdbce9de9cc032cf7af6df2d5c658e04121a61c58be6848c2f5ab07291394bdef46b09720b985cca5ff6d22bbb5a4b3a4639ff19ca49fe80f8787c30934ea92eed3694a6ba93c0dac840eacd05a0e6b9a2d430469311fee6a3158de0c2ff38f
+S = 7fc3737dfc4bf283bb8f8aa2918af4fb7156703b4870f679bb76e079e561d0adb7a21bfae94e21b83edf20bd28d6c06505109bcdd000c7533a8ff9118be14cd8beeda9cdae6f0735d75fb80953bf28587fae51e024d5b415664b3ab9c26abbbb7f2461d9bf7f2520ba08a09421939fd661d5e3dd83f3e4c41f760291e1c081e8
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 7948b018e9d0772d84bdda094957387e91179fd7ed4483091f764a2077d37b87a54f4d10069584e50314e1d866c01f1c22de215c0cd1ffff3e23b321378c1b53d0d517aa29ac262ce86dee0ba752958fab5ab69a3a0fb6824ffa8554d4b212f532611b10a28faca706391ac2bbe04a9603e4f15021ddbb1d47505bee6ba83c28
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 2146e1bf9d75336d7bd76091527567c9326df14a810cf39d22eb91589584caaecd89ddc1b3ef0782e79e535b0bdce8eba2d7f40aa05720278e6c3ed8fe58974fc1ba6cde3fdb79284b64eeb5d08fb312eab503fbdcd85c240414b8a9fb726f38e2780d2506381d90eccbad3c075c7fee67e8a1da037f14fc4a6d8f06c301742b
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = eb2a75ef219b2bec0987c2623a76a8d3c292754519c47f8d541aa8cd9b6c7b3cdd3f7825c2e9ab33e2f684eb34cbe27ac98971b1ba34364e5f15687dc15c829e520a9649dc0ee48fb8aeab8340293ffa869b5c8e4720bae91a3ce140ed7b3f1db25478625653fd8bf378e03346dae7d9638fdfe5a7d032e6ef59bc1e070fdb40
+S = 885c184cf7e40453f8dcd49e1336c91adfc070ae886b23b561cf444092017a86594dbc09c484d6307201633b4476c480994c4bf0a38195d9e9065dee62f5510cb0d9b16a5a9e0ad86eee516a090809e599b4b7022333bdc1c2f9b0cd181a897108c8db6e2abec0c9c6acc426e55ceb9cb4dd565af9d0eadc24ad33bc6a0f2f9d
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = f1cf2ba2463023a1d329957cf3fdc044ffecf8ce0a11f9b6ce8b7ba5e5db07d03d8d08c1c61b255a6d0ece174e661593253cc04e06a69cad4fdb1442da97014e77c1c484994c93104f5b10d876a820022e26fab68ae57e258c36c9ca501106ef87b38674278b14cc61578248d48b889800f2cf8ffd9748266ce6c2c4af0fbcbc
+S = 56c800772a63baea87e02adecbe6e7a1cbf352ec6c40d68d02035a8ef54e3c5d4e4c8d23a686d186ab783dc0115ff56138f05cd0a88a28df8304a7fe8c1f944acff2c51ba447d333e97a053aaf222bb6371c35d37a3c7345f7ba81ce99baaf2f165c3a5f0d9a1200da7017de8ab65c35cd7d082800fd13fb87c37ceff83e3dd0
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c084f86c411436b0111c733c5642186a98d5a8dd8cceb2746ccb8342c
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 8b61c39efa507e17cf4d575bd600286d56a40e84f35d6c06d3cc33b400e161220df1c86bfd0911226081008cbfd4fa0c3aafc4de70478d089ff02f8e0cecb2e6a68011abe64d4196f9de70a9217e8bad594c02df3891cfe71750b509761fc59f9c3627c77ec61759e28c2e1cc4a5e339f9a451ef12e23b8983154d8d0524a437
+S = 1daeb428f8dcb93c16b0b96a23708a4a0b2e70ab7fcc2fb16075f901f94fc9bde149b26c83738e58dc598bf4e1c53b34adb69d93f30726a174ac87c1a1b67bf70fd83fb9b89f476fcb13cfed84c2f6d6a92294e0eae0bfdf91119cb692b096c9bc3d242a31f8a979f965fb983031b8f33f18b1713cab83c1391005a94b79ab31
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c6c72c171d3d71a0bc8488c39813a0b20e2e937a13d9484f6c5de23d1efefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = a6cc1c55dd9b8da73acc6716344503690a9db27bb439518719b41da28284c9894fdbce9de9cc032cf7af6df2d5c658e04121a61c58be6848c2f5ab07291394bdef46b09720b985cca5ff6d22bbb5a4b3a4639ff19ca49fe80f8787c30934ea92eed3694a6ba93c0dac840eacd05a0e6b9a2d430469311fee6a3158de0c2ff38f
+S = 7d914ae58407a2b981e58ca575a81796a5d3d7073f6cc3b2641338fff4b963c35125e99360b8bebbd12add1919ae46f84c67b642b43d48360785d7d990bd6b23a24feb54925575a46c2e49d5ce16204ef0c921a25c31fe0b5ed623b2a35be5069b7a7fa57322a9fdcee5b391451d49e624fad211494ac3230efbad44cc5f739a
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 73b08114f6256d434c5cdc278a9ca697ea2447895884ce05170dd41d5073ae0b6e346ae64fe886287151e0c6aab0aca3638e5b82d63aaaafc50f8070b592cd052ce7bec9306ddc4760a6f6f2166e40800715103f938698a68a10c73ddf524c6c6e55f76f7a0ab7058cace263af7061fe70fd93ca62884d232195a91acc38af2e
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 6707ff06f4e6fe6cab612b8deb099ac9995511ff0f43fd42f9f1822105e6c78cf6e7bdb117f5a8d554000aeb22c69cd0beb7cf1eddaff92161117f08befcb01605e3300826c87f2fb10f6e34bde865db2c5b7124d3273a997b115f3d0022d0cded54daed0b4ddabfb9b39abec2f9b1e052a89c4d64f38a7649729ccb14f72650
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = eb2a75ef219b2bec0987c2623a76a8d3c292754519c47f8d541aa8cd9b6c7b3cdd3f7825c2e9ab33e2f684eb34cbe27ac98971b1ba34364e5f15687dc15c829e520a9649dc0ee48fb8aeab8340293ffa869b5c8e4720bae91a3ce140ed7b3f1db25478625653fd8bf378e03346dae7d9638fdfe5a7d032e6ef59bc1e070fdb40
+S = 43a9b4ac08716a3fa5e6ea8fc5957492d093b3a4293df69efae3501e938dc25f551bffc491abbc1059543280c8f48e5c97ae0fe602c911eb894804ee585f2d3b9de882856ba2bb4c86c6a14b8126cb02be2ec6303c228dfb892d3786ebd2a9eb3247581ff7f01a2d0f6d4c75a96dcb4e98fddd204eb8d191f0896506fb72d2ea
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = f1cf2ba2463023a1d329957cf3fdc044ffecf8ce0a11f9b6ce8b7ba5e5db07d03d8d08c1c61b255a6d0ece174e661593253cc04e06a69cad4fdb1442da97014e77c1c484994c93104f5b10d876a820022e26fab68ae57e258c36c9ca501106ef87b38674278b14cc61578248d48b889800f2cf8ffd9748266ce6c2c4af0fbcbc
+S = 6db3e5bbdfe86efac37bc19abbd07d9209f67876d0ed8f8859b1826d98eb22fa093e161274e4a38675cb76224a70346730314f08475db6ce6fd77d840b9de3063c88e987fb244ac823e962b31ec648ca8942e378a2f7ccf7400b036aea7c5a11e694d85c3c929e43613178eaade378d3c2f6805a14d94029f4a5ce89a87651d7
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420659241b16b3fb30e5012378eac6d83b927e7fc9d0eb5a5ea9d1b75d48441a6a9
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 8b61c39efa507e17cf4d575bd600286d56a40e84f35d6c06d3cc33b400e161220df1c86bfd0911226081008cbfd4fa0c3aafc4de70478d089ff02f8e0cecb2e6a68011abe64d4196f9de70a9217e8bad594c02df3891cfe71750b509761fc59f9c3627c77ec61759e28c2e1cc4a5e339f9a451ef12e23b8983154d8d0524a437
+S = 87ee0da9c96d9a17f63d3e9e142181c0979c381ceb769a370545b535abc6eb8981d3fd4029f529909f620d2a00f209b6ad7c8f709fca13118e00a2f21086fb3a4eb4e416a0b2a121e4f7be5b172a8ed12185948cdb75575fe53d883a354f17baae73fe464d85ca0519b980a4b6f565bc0e76060f86b4cb3e90b6c4b9902f5bc0
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004200d04ea209c27fd97098f416a6410afea38ead35d43b7a1f93d7ae04f7d62d502efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = a6cc1c55dd9b8da73acc6716344503690a9db27bb439518719b41da28284c9894fdbce9de9cc032cf7af6df2d5c658e04121a61c58be6848c2f5ab07291394bdef46b09720b985cca5ff6d22bbb5a4b3a4639ff19ca49fe80f8787c30934ea92eed3694a6ba93c0dac840eacd05a0e6b9a2d430469311fee6a3158de0c2ff38f
+S = 8be4adcf1f21261f16ed5b4ce29284399e2a6b7f6339ebb94fcd8c412827911eb5e626d6c83315a59db85bea8010ccded74991f98488fc48989b1854619acccb63fff3d1e4e9a350440744e8bd16631f39ef2a1426b8ffc33418dc7a2a0bdd3330b0bbebba1f0b9fcad2347a875dd89feb43506c0d8e1476e36c9fc6a2798ec9
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 70fa48adbbe7f5cfcc61dd844ec0948d8c20ca5bca62cafb0d7014413350c5fbbbaeff1d445a7367420b1237dd316db6c8298d5ba13a3b26cbc48a84081bb12848cd8acbd198a7250d0411ed8d0e56d0163c39853b3893655037f6b4774be21d62c604522904202d6aa0f11aa1f7f56612e85139ac0d577593586d6229422289
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 1a7aa3bb07684cb72a23a570dd06eec11f1ac1e5cc02108b6bcd7145c413c743da8706a44db575b7053573e975ea2bc111821612f14aa001dea6551863e34af0e68d6f9281cccf590d1b2528085cb8e878a427d320c73806a3af8b498b7d3789b66dda4ba9d6c26d15500c71a6b663d9612076792513776921503435d6578b6b
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = eb2a75ef219b2bec0987c2623a76a8d3c292754519c47f8d541aa8cd9b6c7b3cdd3f7825c2e9ab33e2f684eb34cbe27ac98971b1ba34364e5f15687dc15c829e520a9649dc0ee48fb8aeab8340293ffa869b5c8e4720bae91a3ce140ed7b3f1db25478625653fd8bf378e03346dae7d9638fdfe5a7d032e6ef59bc1e070fdb40
+S = 706c8a70281ab07dca9ce73757279e70621358f1a5bad91bb8d0f34a4519c625ad000df75709b7fc805ee64e1a0e8b2f5c637a833b682c707eb21ad79f99d9f82aa91ca1f3ceb6da9c117c96391f547297cc8f507cc4363f9f2ff84fd9c8f430e84740f3d3d9f385e73d90c8769da2615e46552566f456f6a675d613b8a97678
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = f1cf2ba2463023a1d329957cf3fdc044ffecf8ce0a11f9b6ce8b7ba5e5db07d03d8d08c1c61b255a6d0ece174e661593253cc04e06a69cad4fdb1442da97014e77c1c484994c93104f5b10d876a820022e26fab68ae57e258c36c9ca501106ef87b38674278b14cc61578248d48b889800f2cf8ffd9748266ce6c2c4af0fbcbc
+S = 5b3567d2742f596b42cd2e3951f75b8058a98d822961f5deed17ce86355fef06ce8f1b1e83da9f27ac4203d2b6a406ae2657993624344fc760a0ade6106028e2dd68646f1c6a735547aa7e4d4e6ae1d3f14610d5eebc88dfeeccf979d93f1721554c67bdbae99dcc2efcf3a98eeb6bf713dd3c5fbfa44e3b9467838744d226bd
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430582a092df1f38834b32c013209c529a91289d7e595d648c1a633680988e5c8f8153c37c9caf89c37578d4a5cccedf712
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 8b61c39efa507e17cf4d575bd600286d56a40e84f35d6c06d3cc33b400e161220df1c86bfd0911226081008cbfd4fa0c3aafc4de70478d089ff02f8e0cecb2e6a68011abe64d4196f9de70a9217e8bad594c02df3891cfe71750b509761fc59f9c3627c77ec61759e28c2e1cc4a5e339f9a451ef12e23b8983154d8d0524a437
+S = 0a23fdb9060b70ffeb690d0e4be5201499f3623663c4a3c5b8ccd937c20523fcdf526db4279d7d7f1067e241b0d7f00de2841934691747976f3c63e68048702b69db8981d8efba63f0fabab14abf2f517b0d5caab537f187af9f46414f070fa5c1fb9d2eb6858476a5af8bc82b7c38aed298f169f1b962aa452e5f6cfbfe766d
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffff003041300d06096086480165030402020500043061ec010a79fc79f61a9051dae86a56fd57b311f7d5043f4519aae525d02bbe46a433dcc6aad89016c6298dd09ea7ffecefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = a6cc1c55dd9b8da73acc6716344503690a9db27bb439518719b41da28284c9894fdbce9de9cc032cf7af6df2d5c658e04121a61c58be6848c2f5ab07291394bdef46b09720b985cca5ff6d22bbb5a4b3a4639ff19ca49fe80f8787c30934ea92eed3694a6ba93c0dac840eacd05a0e6b9a2d430469311fee6a3158de0c2ff38f
+S = 9bda2d9a6a3570737eef2c75f5fd4891d9e8acc102654decc8321b2e114ae8c2f615a1173d855e5d4261a99dc7f825fccef11199e57ba30d98502c237761217261dc31cd14de68201278ccfb46459323d192fdce1577a1a9098e5c7117bc0e52ece3403e0b35fc64969342a72ad74e0330a10a50b67536b088372514a8436de3
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = d3787e2cd5eddc154a3b29c8a5161cb0ef6fa97d6b90c9d579677d46ba22108075fd9dc13958d290c40df3ae2400224a1cf8dd74c9adc8d48522ad9c0c34c1bbde732954e432bc6e55da0beddb849ec1f2c6815d91cc006a0dabaebd3af3ac87d38327cc1ca22317c54b776b12c7197c39829c1f0c17f700d7ad88938c86594d
+S = 3892627dc93f65857a6e773202ee6d8bfed806ec2580f1f63fc7bb547d6ca2d2459efa5aa6cdc9513153ef2dc2f9acc0a3f878c4b3a149b674f246842610ec9d4f8d2038bf1126632b588b7c8376066d1b18d85e51ec221efcb5f58e6f3f4fab1fb6b232d443cb16484670b1adec3a450f9f926ceee02c6ffedebc4664a9c5bf
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 31f8dd3024b0487ae1e3a7af9032ef7c76d5420d617771814747c09b2a4ce9ba3ef8630b4e01e3fd5c6c24f588ebe44433682f5663e2df2b6978640bc2c3c1763c69d75b59efe68af8cf516a32cba1ef8380cdc72a3eb9d4d217fcdf7136e68b7173c2870e245808ff35b677587b3066af45a6c97d340563c84d107eff4d61df
+S = 6015144a01c388c92bd4913907fe075a42afea023989156b840a493f074d55164405e50a4105d5ba9810a9c761f4626e6e05bf7ec4b47b07ad459ff404db6931f4a994a1911fc65448163d369eaa61674ce2112f79a7a9f541f26a111a605b9a3aeda1db6627c59bf723d34153769d18d9ca724570484583b37ffbb11bf7d4be
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = eb2a75ef219b2bec0987c2623a76a8d3c292754519c47f8d541aa8cd9b6c7b3cdd3f7825c2e9ab33e2f684eb34cbe27ac98971b1ba34364e5f15687dc15c829e520a9649dc0ee48fb8aeab8340293ffa869b5c8e4720bae91a3ce140ed7b3f1db25478625653fd8bf378e03346dae7d9638fdfe5a7d032e6ef59bc1e070fdb40
+S = 45d7f419feda3099092973f1d61994225fec873a0467b1348776a3a6578a10b24be941000311519cf426aa8bdf45a300d7eb31766e0516988cefb14f076c0502a9f7421ff4965875bae992930322d34555cd32ec47d8e6b1ddf95cf1eb193ef3accea5db5343a80d0d36d4325361c7180de57dcd80929bcb9fa166ecf930113c
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = f1cf2ba2463023a1d329957cf3fdc044ffecf8ce0a11f9b6ce8b7ba5e5db07d03d8d08c1c61b255a6d0ece174e661593253cc04e06a69cad4fdb1442da97014e77c1c484994c93104f5b10d876a820022e26fab68ae57e258c36c9ca501106ef87b38674278b14cc61578248d48b889800f2cf8ffd9748266ce6c2c4af0fbcbc
+S = 22a5c4a08adf1a8d1dc26d0a3f02af5f12062b82e10743fbc2ae74b0bb533de279bb57bb6f0a44f9b79c2621c426e9e6b5f50a5a8a2df9d46ce9fdbdd0bf6e74cbe2e55682046145a7e40622bc81ec945e8b87a8a9b9ad711e7626109772b64be7a7ad7d5f3b3aad20c03eb164716b62e0851f1041930d4e5ef4b50bff82f425
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d0609608648016503040203050004406aa75a3539ad3822952b91897813389ae2946b072578bea95a64f583bb5eb9a27a8e44c2405a9681d9a290e2cd55fbd59c381039de0e21ff120d2a3ed8889277
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = 8b61c39efa507e17cf4d575bd600286d56a40e84f35d6c06d3cc33b400e161220df1c86bfd0911226081008cbfd4fa0c3aafc4de70478d089ff02f8e0cecb2e6a68011abe64d4196f9de70a9217e8bad594c02df3891cfe71750b509761fc59f9c3627c77ec61759e28c2e1cc4a5e339f9a451ef12e23b8983154d8d0524a437
+S = 088942923512cc272b5cd0b40d4aac42ea3165c74c90970ebdc46b5fa8c0b0e153f85c446b0a2d3886c7fd468a47efeba91550c7f01167ce009a4d6a3069bb280b6755eb9716c03f64cd2788555b9f8a0e85d74879dfa9c48ba3ff2002a8b0de02cc8479ca2a59966994d36c6622f4297e2a26cfaa824e447a6badb92331829c
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffff003051300d0609608648016503040203050004409bf5087cc76d346579861f84faef10011e190ef00bfd9b708719d5b672952c0a5f5a8fea8c12b2d738e0b420d785e6a02d7352b6a0e3d20ea2c2140094278b52efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04f7405154be02c482bf07115b27fd7f988920d8207937bec317f1791c11b0f2325851c35ce42bebc828c946438cc22656b702cce2a0dad6d8a5ac3fe6fd587c36f81ff5edc977edf9c6c085efd73510ddb2532742367f8f878814c1714549dcfa17dbd5d1e17ce3dd1a9893a3785bc34c5205df3978071aa36c9e86bd33cba1
+Msg = a6cc1c55dd9b8da73acc6716344503690a9db27bb439518719b41da28284c9894fdbce9de9cc032cf7af6df2d5c658e04121a61c58be6848c2f5ab07291394bdef46b09720b985cca5ff6d22bbb5a4b3a4639ff19ca49fe80f8787c30934ea92eed3694a6ba93c0dac840eacd05a0e6b9a2d430469311fee6a3158de0c2ff38f
+S = 82f547779204eefa0d857ae077b2e02e61dc76ee75e709388ce33b3f227dc96c5a98148a816a4c954516a7e44b00b080cd8b05cfa4ae9ff82d64b811f62e6752904b88c2e4a9d54088a49d2d480c267b96974c46f75a4fd9cf09acca14290d6515defc75e0807334cba3f492d42a17dec01396e39d7d8335bb4d11a1c19db3d2
+SaltVal = 00
+Result = P
+
+[mod = 1536]
+
+n = d2b6c8fd44e7eb621fa6685fb62371872b5e8408af51bd1b44c6473823402418a26963b98e6fb191cf74175e64132ae6cd101133fc002a89c10bf7739eb930b9c067b52570842395657f927434aa3acbf3369dcdc3990f77cbf22939ddd5877f09c8aab818b80aa20544b6928fe62c78795a4160aecde6ab454db0dcdf1d6c13522526c5ccf82d429791059306f02cdc18c4e580ec6c2da19b3c6de63933ebeac79010c73df95748d987e96a0f8ad523b5014b33423f55922aec2ec23b9aa22f
+
+p = f260d143cff1e8e0931765da8cb335c0206bf7fd19aaf8ff41e762992f2bb0a660cd65f08a80fe502c9125166a6927aa1859a874159796fada835b48522f5795ed1f8d23f05016358ff908b0dd638bb7ed12c8b80b46aa858d52c77bb7fc0ed1
+q = de8e674fac0b7ea32d518a22030fd10d4298a77974db8febe195a4240dc5373e8161baf8ce47dc4fd076f64e307ea6262c35b9819bac4f142b613973eeb6a62a15a2ff09fba9ce4db7186969af925ee3acb7d3be7a1f9c85358216640fc1e0ff
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 95e319c0df793cf1c1b424a8949b9529d6c1a0cece5f6db573a538b68b529a9810830a84d7c8a3b9747d2882585845653c3e179ec35befcc5a7153e96370467f9448ca1999fba2f801f65c0857a18f138f356233a5ce4d8d80c1243c1c2f518ce8da60696d38c21731c6ca23db9ffc99974d8777bcdf1062ad3bb198fdb64226
+S = 1b5d13124f4a0ba3b4e8f102a7044d8a633ea025729f55ac75e4a8544612f229d4f43c45574983b51efc83ab611a60b009949dd032c97358bb7ae5d3b2ce417fe11a9f6435b84bf7113b23403b010fd749838823450ec954f6e3f54c13db12606ead2eadbf209d5d31efaaa0924f256d3f64692db8a2b7fd8197df13c33b160b2f8fef0d4f2ccdd1e1a5b269b25e4efb462c000573b8584d45c2cafd248348f19cf1f7422abaa402ba54274b7611c4c9db3a7dac61ce51c396cc3c59ecbe5594
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 7271bcb91b18288e874f4c04c10a21bd35150b1813ef61a7f4dc29e4c036231fcf040abb4ece169ae5afc5d696abdbb2e943a7d0464789a4a2ecb1285e1e29d16b1716c2b3313b41b4f8be676e842f1b8006c6418ea0ec2ee57afd5f62124d6b90d3693710ea9f693e55c01f113c24e04385efd3b2a3932e07ae96f295b996d6
+S = 6b9212d017ad9f4bb7ebfa3975b514bdd22240d753fef5631e1c216bc750336349255d53b857bc944d3eee3bc82805620d770e41dcba45869f47d36343ef067cae99a941ab94948bf0c02d2a3ee403c7eab0f9d6f9423c166e62c2dd61198046944b5082db4a17843229489c46baab712416e3d0a685d2353abe010c94ddf7b47f5edf1fdfc9a5e0de27d65ab5dfc9f2e660d20d169cde3e2642393edd79fe7316ec4ebe61fb88223f6711e138d09ec3d76781e73d93e7dba9830c53cdb5b0fb
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a050004147c3d3d4d94e5e297419551f26b517d0046a98d9c
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 1484f58f6b8cff56ab4b81d17967dee7ef1eabeae57c11706fd2735ea6655145ac636df2ea1b2c409c6c3e31907e813d2ab123eaacd3089db4966bb00741c7c48ca5f8599c539d9c790cc27f1b79bc0f331c53036a872790e9cc4c851f343893be34dfec079c1c11481253e4a3bf55051048835ba50037f1165c5f0478a76b5a
+S = 57b3646aae17304bcfab8b6477bbcf791ccfb4b20001b2c3cd4e6dafe129934f2c401b07eada6a4b2db9393ffed36a8ae8af85b1d433a398399fc0c2956959e99c12053ac3346710ea5d9119fa4757032fd1739b426e879214afe364a9d274d383e4d1fa64b0b07c6f6014dcbeed59ee0dbcbec90cb5f3133daeb829855d61b88777d806b5717227a8016a965f1bd2080b44ef80bdbd0bf0c494ea7baf09295aacf161c433320fa81cfca5ba44a71264a1d1db1d2f5baeb58eb9d623710ed1ba
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 957018ebbf4bc279aff3a28f87510c01666122399490a4c300680910ed6ece73e84b0e70fd2b53362a63ac6a1456ff26f999a142e65524d22aed70ef0ae115bbb6f3e09f7c88add73c507b311c29c6117c4111b92d7bc2c7dd1532ffd687054be9aeb700a4297863cc043a6c079308cad8a19926d0cb25ac032677c8ba28442d
+S = 7d9edeb96e2eb21b32fc3707c42fc26cc2ddaf5283ed2853206e51594027fddbc82260dfb3e2da03dbec1069f0bdc63a7583f0ffc194ba158860fb0bd13dbe22ed34f7f77821b58ff1b6d9a6721f91914d3529d5e605b813f7de832afbc57d7ba570a4af8f9ad2b7ea8d2c1656c669e1df7d3c112bdbe212d37d61ff62d03d8b19426437a48977ea5aaf5eccdb7d90d1e8a1c652cb2333984cfac0c1432e42fb16168a3760328039d1a836a52baa9be92050e96dc86d37c8e0b0684d445be018
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = af0272c90402a9c27f9cf6c9de652cb7a3a402b4695a0c58777fea11958fc0c51f45e6b857a6e0afff42905628b7aadf457669ec83ca80af5d16544f6a5e688e7a0818aae2e48b80146be3f77344b69c650dc28aa957dc8debf22a87956c9212e9d472664dc3927ee59e5776671539382bef7657820a083b499dd57fbec12797
+S = 3cb0d524151a8e3210123ac13086c6299074f5b5a4276059cc2e741944eda31a80aada9427d0a7e49823632075093e4f779f9b84ec4f159227e650c267cf7126047f7d257dc6e41ec6113570bc231681667735d41085ea92a2b9197fac8e4ec9bfff1d2b16f65ceeed22741a872a05afd641b1444a928a948d15248b119f28b3d35e28a337096cb7bb97e7e3d73bf1cf8abdad9cbfb84481a3e124b8c345a2d1065b1713de71e0ef6b8beddb6d88e82379960bdc1cda7ebc4c4c4ea9bd1d81dd
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 3797ad7bd2b5c611a7b1a15b8337058a1e2c15cc42418d7b2fc949943fc8076cc64c6d9e3c004e489efe297711e5f2dfc92b15d029b5b9652ba541ff037419f1ff40af7db267bf005154d4695d990cef823e1b04c0599284c8df6233a9ba9b66ab1c7a007b12a3a0895cab19af7cd923130d2e504e56a241ce1fb11978c31632
+S = 0a34ff5dd8d7ef76bfd56bd4218ad50c22cee0af0532674427c7e13f8b99b86e7128316bf2084c6477180283a7b3f4f4aefe5e0dd4aa136a2920ea70eb23b0e8b8b2c2a2c530f4efa1b6bc59d2a83547cd5c4043ce497639f609f05f3d4d2099b07d9bdc0a15690b7bf2da73def963eeebe118e59ead6dd89f0fa271645fca4d9bf220080a850649f48709bcbcc1cea3fce9618bf167e2fdb13a1ed50eea093d1070c5bfb162b054317f2e41bb3099c39d8e2c7b0b771da05cb7b7bd1abfbfa8
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a0500041486d9512b229032778b2d54e07bd553ebe7f36713efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 95e319c0df793cf1c1b424a8949b9529d6c1a0cece5f6db573a538b68b529a9810830a84d7c8a3b9747d2882585845653c3e179ec35befcc5a7153e96370467f9448ca1999fba2f801f65c0857a18f138f356233a5ce4d8d80c1243c1c2f518ce8da60696d38c21731c6ca23db9ffc99974d8777bcdf1062ad3bb198fdb64226
+S = 19ca086cb98c4770fbd6b70206c3896f966c968c1e5600a2348f3457fa823f053b45b75f0da759994d5d047922efa5184fd0499f57be607a9ac63a1926f8317e6845934a37cd58c07831a970d9599dcc15fb50c629caff451c96e2e2d7f9e3842e8dcdb8011adc8f5cb1c01392218d62285442d9b651b2a0369af3f99343dc8e24fe4f93fdd490636e78ca1b7ae73af5ee2bc0ab6a0fb42ef612c3260f62a1577c3b41bcc25e8feaed1f53e0d85c8155c9c38cf72385ae28e96831f891e03ad3
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 7271bcb91b18288e874f4c04c10a21bd35150b1813ef61a7f4dc29e4c036231fcf040abb4ece169ae5afc5d696abdbb2e943a7d0464789a4a2ecb1285e1e29d16b1716c2b3313b41b4f8be676e842f1b8006c6418ea0ec2ee57afd5f62124d6b90d3693710ea9f693e55c01f113c24e04385efd3b2a3932e07ae96f295b996d6
+S = 843e9f1f0a472be4a3bdf456281eda82aaaa08a0fab173f2086bc03f8b88c0517f457bc276ad144c1b53084d736f2077b0c05f451ed6544a36bd26e902592b384c6d33587a79f2023226fc7c52b1384bc6dc83360769014fb5110245b2395baeec2b3087f6b6eb5de706d08fa7eb069c749a56b91d43d1ccc8f1631a597beaa6486a618b85a2982eb32fb5039584c65f7f07e7c31663a06f48941878f1ef4cbb657f18cc85db6e9d1c87ff81fa7b1e63c74abda333de6242a21a43789749bdbc
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041cd6266f6d4d47969031bf6bd3800efb1332f5c75ba7d91394de470bb6
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 1484f58f6b8cff56ab4b81d17967dee7ef1eabeae57c11706fd2735ea6655145ac636df2ea1b2c409c6c3e31907e813d2ab123eaacd3089db4966bb00741c7c48ca5f8599c539d9c790cc27f1b79bc0f331c53036a872790e9cc4c851f343893be34dfec079c1c11481253e4a3bf55051048835ba50037f1165c5f0478a76b5a
+S = d140b01f9d0d67a4b869fa67c115919268657f97d846886f07174fe6a30be909a74f1dfc4590ea356e349bce40547539e76bc9011ea133356c6f01b7739126c8af29e307966bfe39999625ef989faf817d0ad6378fe5dfcd5974089349d977c7fec62289b760b4c7679d41e463be7e3f996cf1f66e48cc004f5823b1f7a94524abd06ff35fc4f51fe6bd16dc4b43eb360ca18b4c4e5a33440d748dc7fb1ec3a8344f4e175f52479f4d93275e03890664fb3a2941187bd023a3a277fa840986c3
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 957018ebbf4bc279aff3a28f87510c01666122399490a4c300680910ed6ece73e84b0e70fd2b53362a63ac6a1456ff26f999a142e65524d22aed70ef0ae115bbb6f3e09f7c88add73c507b311c29c6117c4111b92d7bc2c7dd1532ffd687054be9aeb700a4297863cc043a6c079308cad8a19926d0cb25ac032677c8ba28442d
+S = 10699cef91c348ab96ec062c0a98bacec04aed2bc2a806d8553258ebdc999abd59651e8aa7236e50eaf0a183e278a956de7ad6c3eacf7e5a2dc1e46a5fc1ff58d09db56580d924de5c3ea9863c006cd9f1556555b024a670c316d2de697976a3ce5d3994a758220cc83cffce43f7ce42942c3caad5a477c494d9581185c4e5a69f056778c77784a7fcb246f3edb1cf93bd416057d0c2ebeb36647ba8796b50ea569930132d189cb43be8405ea210b8e2266807620487791839d0e6ee4dcf9d63
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = af0272c90402a9c27f9cf6c9de652cb7a3a402b4695a0c58777fea11958fc0c51f45e6b857a6e0afff42905628b7aadf457669ec83ca80af5d16544f6a5e688e7a0818aae2e48b80146be3f77344b69c650dc28aa957dc8debf22a87956c9212e9d472664dc3927ee59e5776671539382bef7657820a083b499dd57fbec12797
+S = 90277451b160d24cd2df6e5e84e2f90a8fb6208f3395a305e299d5005656a153d27801084f7cb76fd0e4b8d118f84214416bc65446cf41fdbb6532c07b718ed82e34a8b5b52575e39de48e65eddeced22e5556d89103960a228df0efb047ae0e1569e579b477b38198045bc3f4cfe021dc9bccc33f10d3ea30a01c7c567ab22bd2d0bbec9c57dc990bf0ef19fb5942f116ed33510ff76405ea1cd99c0b47ac687d8c66f9540685d831302c272de04b4459951ff480f99dccbe3b0c01f3330560
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 2da2547df2b14d5f28bd5cd71250f55cd840a11e7bd799470e30938124e4dcb985e7a72325aca57f5690d59a3c759e1781ad1b6f4b1bb6376b94f8a2d88b9f465beef1238b4b51e1fc371059b4f08557de41609ec3a63b2df5b172c1cdac359b1880db830ed6790d847bb41b6209d3a356c419b3cac251b2144faae8ed8fc541
+S = 8866a8d6767eb3a88cbbf6075ce1ff085e541e3dd305915cfa2ebc94ce8d6ae9b7a76d5770bd4e96b913fc41824b59f3066471b054f744efe0fda0f12fd1413b755f0c1d93fa3bfd00dbac16cd6c83a947d71645aa3828b7452aef6b68a92f83dbb48a041ccf1905e10665e186d5aa85e502b36dacfec5b1d17ce9500caef5e8eb8b51cff080368b75baaee54886e602e722d2b9d04dbf05026624ec6fa772830090c570c5b8ac7594abe3ab312d46fa3294dd96ed9c2642672154240e66b197
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c9d529ed5fc99f3b9f2d3c3abce14aa723e6ee9397db13c35a355fb87efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = df8494995c51a92e651ecc6229ec4c5ffc54b2975876ea582233a3a02f9cf73207a94fe9e92f814d0f0c3c6432a4a6cb51924304af9719121bd612437344a14e6b5aa89d8b0d9aec77ffdd1373f77220268fd7a99e2c2c61953396e8f37ae1e894fd695d4ad33a3426607618f3cbf78904b2362e301d6b6c1ab1f637b627fe28
+S = 8474bb2649667bea417d1a51fcf6cf891c29d838c7002d7189b945b53436cc0b67175e910e2cdbd3e1855326f7c0c823a8b76d06b2ae1e0bc6a835a524401b5a280d07f09acd94ee745e1a789919128c617a683d1b145b3adcc494aa701c2fc5895d14ba6a7798c3fa51a04497e78413200b284a4b50bd82f0b7a1a4b3b5b3cae15e345844b0b7f155e48bc52fddc2a83648b2714daeafbd0c8c36de1165cdaa75bc8442b681b9ecc1cae114e629b13956734aef0ad11c421ebcc27202df5899
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420351b72799b9cfe54802309d2be3fd5ffc3377302cb171d35af0d486d4e664516
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 73a012bce858e0ae42fa2893a0fb1439a73a9c101841b28ca8c8bdcb0c7b497853fefdef782dcda238a871bb218f1503ec8a52020c0d5d6887da7eab05c7c4f226c1f8321911cf966bde63251cf3e49ff8c38ba724aad027f876ddf10c2642a296f2eaccf38b4e5483a3e818bab0ebd574ed314989a27594a2a6c2e44b222b51
+S = bd0512605f506b906f012de9f50ca56881c61edc331d8b36996b4eefe75b4751b6ff980194b52e19b82dc85fb3428c86905aea1e59e9db90018ad5471e29ec170f18b9668725a562caf850ef41c7ab871448a6f428db6b2ddf85fddf029dfbbff5677bd92aceaa9372f9a579a2f7fbfa8872f8de3f7b15c5095598d39b3808f99cc672d89171302a7e7c3430a1ae675cf3d1b3341f432b4c57a372f9be3a06970f2c4ee3f557b98a8e767db450ff29a491163330bb3438432c5dad3dd8dffbd1
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = af51ab7e521b64502702bd561e40dbb41e2f80afa95bd562bcdc67b3f6e36f86fd9256311e11782f33de2918ca64f5d083d02cffba209fc2667ca4a141ca60c02a7d4559c7add9696e6db9aa4659dec2a96e20bacd1ff8b1a4a48ad20096e383fbb97fdf96190e67a05877f4da461ef158b263c62a806b973cfc222f7b6e8037
+S = 6ed6b46b522f09d6c1007dc32e593a2dec403c5f318e9ce0edbbb2ca6b9b05803ba43c1828ce2fc0e2fe8feb4f80db80e1673e111f204a6a009c115f0a797006bdfc5b5258404e259aa0f9d72957d01f92b756daa9981952dddb0bd1b1aff6caf46ccaaab62a15f52c79fd663ff64b94ab8428c04780efe11ce1a210acd89e63a26f4a48b9e4acf7c327521a9654ffcdfe03c6baec5cc8bc32731d6a9254302a69f56bf43ae8b82738e8073f073dfc8c386d9adb0f1acf16e59710e4e519cb42
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = ae4dbe3079ef09f963a3da04099f596a6eed3c979d798eff8f69af0d4eac9d5c5bd6712a4d2b2d0abcf9b4d85d2c1af26e1c1ea555a9f5e6848a4a439fe28219e1144406bcd939a1bf901069bdd5c6fc2c54248acbdf898888bfe9a9a048160a08b13eac0c22b528360df59e71c2e4ef6e3e552c4744d04e62b096279907e098
+S = c7ad03de788a43496f2ebed7df3179788360095e880785bc5f9135be256cbd7693ff1c47d7dc74e1e3f318a533ad50850336d64cecaf1b6b6a317332810d433362eff2b03b6730df4a04ac3c69e18e752577cf8ba9bb0981a2c6cfc2178fcaa3bee1957cf10a74e87541a3311e40206457a11efcf76893f59dc78cde650b0571072a9af5500dc76cfad2bce35057768b97046adb84a67efce9d9f569839e3f36541cf0b24862f8311796edb735476eed85d8290619b56237a89028c92b3eab48
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004208aeae1f557c4b574127603b7da392e75ad6df1b94d840cff18ca38033d5cd0f4efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 9245f9e8a7b4e2c8744d5bd42ebe68ca32426a5cf7c5ab78414938cc9888ef8af9dad868cb5ab9ec1444e4e6eda2543e3428f8ef805c4f545afa35a3aa96fdb76f83bf12b3f4f322bf613fc38b2c8e0678856230418b6b062fb358488d6eed7c5c0656ec48c9bbf2da6a1473eea43faa68204f27239928172a3e49c52b58e861
+S = c9e9152887b5111f721aced7cdb0e7368b0eecafaa1506ccdf35c378b633937d08544493a1e8aa84b5b7f892d89976f2ebfd55ae85189f61fb280ebfff5a01fc2c90fa4896ebdc3725ec472631e69d35fc9d5a03447941e7befe21a36ce5cad72088177d7e54cffb60dadfaf3800ca38e9751df2d4fab7738f31d82a944e0f3bf652197121c4e74ce5f170fed950f7a03906e75b7fe12469fa4d44fe8348d5459bc5f5f13aa694c12ac64912a20d694230ed95b75f3de4eb0c3c60169695e94c
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = bf15e4f37e28f61a35be4539f17d70c75d3591c19368b84c320a999cb1858114f3008faf1be1209ea1908b33a67e0ffd84670935aad46a58a7e36916844a756b579a6e0c15c11404a8d3c09f410a5287f00b6a2d726adb6a4a715c67131d81ba146aead115d0bb94710e4b466d2621acc8a91c729334f1ca433bdb5605058d48
+S = 897dd26e35a3833b069c14e173d8f90443d51f3c8867457980f0c20420568290a2e239642fd21e93778dfea2bdf3ccf72c3ee8f4334394238d52fe577d1d050dd69838626922ed9af276f888356349fd1ca8e9c17d615b9d3cdf86e86d01eebbe52dbd26c034e8a93fffe7cbca27edb1d03b13643ed4ad122400d4f980ff7b8a9864d39e9fbd5781ea4d21a06136b70a90fe2bea2ce142334403bb078095f1257df2162e9998a7268d1f05f4c483f726b9b0cfc132023c643b1b0b04b6d88745
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = df8494995c51a92e651ecc6229ec4c5ffc54b2975876ea582233a3a02f9cf73207a94fe9e92f814d0f0c3c6432a4a6cb51924304af9719121bd612437344a14e6b5aa89d8b0d9aec77ffdd1373f77220268fd7a99e2c2c61953396e8f37ae1e894fd695d4ad33a3426607618f3cbf78904b2362e301d6b6c1ab1f637b627fe28
+S = c7fab5c4083fd43b67dcc56c10b5f9a4793ae49411b828512e4930765f496e313995b506e6b2ed4ceb29eb2b9a649e18a1c9f22fa5c89f7349bd7d8e967c3169fdd120517834c0aa355b5bb85b13b0c1fbc2e915c9ac8d7801c37cfdcc45376d8915ab57a67cb39fbe3c976e49e3a47e2312dce0b27ebb2baab9214a7af25482ca1f7d9baaca22ab73deca082b271044048505257c968b131f5dea33c1d02bd4ced74b6c0cf71cba31d989c685e9291789d2a5e906c52268a270ec8206e3bddb
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430ee9e3e985b715474d343f9823ce7f3fd430e13cd9dc4d9117c1a7f1c87f40e16a1012f103c90db1b979cc17934b20756
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 73a012bce858e0ae42fa2893a0fb1439a73a9c101841b28ca8c8bdcb0c7b497853fefdef782dcda238a871bb218f1503ec8a52020c0d5d6887da7eab05c7c4f226c1f8321911cf966bde63251cf3e49ff8c38ba724aad027f876ddf10c2642a296f2eaccf38b4e5483a3e818bab0ebd574ed314989a27594a2a6c2e44b222b51
+S = 28e465b1d7e5e227ca3af797f7f4606a4d78fa8037190e52819b184bb42237b64854c317e08bf3e6ac2e544eb58e0e318682224623f8912682c9afe0e81e7d9f027105c0da1c2b5f27fb24089af422f559ba97839749bcf9e968dca0e58213a0ba53547934804a1e10db9da4464ce7800e5613c89586277beaf69edc62a3e8ca2a8935ac4d0b4d65e7ebff4358be37102a70f327245475bd6673c7d092505f321cb600f6df917c6873625e5d3539d95b94be06d39f90eccb424a9e5acb27f0d3
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = af51ab7e521b64502702bd561e40dbb41e2f80afa95bd562bcdc67b3f6e36f86fd9256311e11782f33de2918ca64f5d083d02cffba209fc2667ca4a141ca60c02a7d4559c7add9696e6db9aa4659dec2a96e20bacd1ff8b1a4a48ad20096e383fbb97fdf96190e67a05877f4da461ef158b263c62a806b973cfc222f7b6e8037
+S = 198f72795be3be9f70828fcfa6fd2eb286f4d996153953730f8195669840b685b1854ebd54f8d1ae8db487802f8c6978197822157eb45c8085ae91f11390e0d8910f2bb51d1efbd743e2e7d7e16c4757a67a666c1e6bbb90fae924550847b68e41bb9d8b58b376c70c075cbedb2875bd7789971d2281ac3a591c7361030dd46afa79ef20a32f68764d40f4f5d689f3686967e57f1b718522a61ebf35e194219f9b044aadccdf0fab455be9f86a651bd9eebab4e8c798c9156880b06f12ca6b7f
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = ae4dbe3079ef09f963a3da04099f596a6eed3c979d798eff8f69af0d4eac9d5c5bd6712a4d2b2d0abcf9b4d85d2c1af26e1c1ea555a9f5e6848a4a439fe28219e1144406bcd939a1bf901069bdd5c6fc2c54248acbdf898888bfe9a9a048160a08b13eac0c22b528360df59e71c2e4ef6e3e552c4744d04e62b096279907e098
+S = 14f03b08b6e55a8aac770701ae964a627e2c35a6e5b0a086cad74eb7cfd5f30c2b481b9a23a03e61f9a73ea131ee9e0d44ae896fd815595adc40a7f719e37d453c6c2ac99f5e76665894fbba102102e31a4fbcc172d523a0feddf5f0098949041cf5c6dd729882db4a3104062f37fd0b51f990d180fd58c2894d9c306e001878aceab5ff4376b98c65864e2216702b6afe97686498732b6259a85e60e56e184515d8326d7ea98508566fb6ff79e771a08904918f19562d28d6ae334b9f15104a
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430d641c0a68fa8724ce04f866e4c8d232b9643ff63669e3ba6b030d0ab734710b9d6ae8c7703bf964d4b827d2098fcb79cefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 9245f9e8a7b4e2c8744d5bd42ebe68ca32426a5cf7c5ab78414938cc9888ef8af9dad868cb5ab9ec1444e4e6eda2543e3428f8ef805c4f545afa35a3aa96fdb76f83bf12b3f4f322bf613fc38b2c8e0678856230418b6b062fb358488d6eed7c5c0656ec48c9bbf2da6a1473eea43faa68204f27239928172a3e49c52b58e861
+S = 7ea67611c9dec51c441cd3b5980e566f13e1191ab9acc5885d12e04c231b8ab7ab1bd388cdfbcbcd6a8c175d50296483edd4415ff4220b6af620e3ab5d2561c0db009e2ed7b094c8ead105d9067ce25c555cd306f52f183efe0bf3a618c5d52b9517ea948cc1a3dc43cbab21dfa74a44db4a34f8ef6aeb9e7fade424122a96f587a5ea94dc9b7399485d2bcf255826389209a89d5695891bae7bcfb22e430a3f5324fbfe79adc7f7fc5b143b86518022a96902fbba5a39275650d8028d3bf144
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = bf15e4f37e28f61a35be4539f17d70c75d3591c19368b84c320a999cb1858114f3008faf1be1209ea1908b33a67e0ffd84670935aad46a58a7e36916844a756b579a6e0c15c11404a8d3c09f410a5287f00b6a2d726adb6a4a715c67131d81ba146aead115d0bb94710e4b466d2621acc8a91c729334f1ca433bdb5605058d48
+S = a7395ce62131a5eac115ea950fe60953fc334cc244b13b159720a502b7194c9e65eb665e6475e1e19e462b735496d65fa8a5c16162d97b11656a85b43fdd4a819ae918d79e50e51ea1e9f5fa92f467410c61d50ce2e3b61f59be2c88cfadea890b71edb70fa87e38df81c38d315b33fe4ca4fdbd5779052c16eed21468a03b15fa7a235e8f6831ff55fe2eaf79eaf466a2280eccb8139dc16c8f296f0e79a1bc4784f37e6550264d7e26a8507b97b1e279f644a29c166be2c761e1ddd7cb6611
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = df8494995c51a92e651ecc6229ec4c5ffc54b2975876ea582233a3a02f9cf73207a94fe9e92f814d0f0c3c6432a4a6cb51924304af9719121bd612437344a14e6b5aa89d8b0d9aec77ffdd1373f77220268fd7a99e2c2c61953396e8f37ae1e894fd695d4ad33a3426607618f3cbf78904b2362e301d6b6c1ab1f637b627fe28
+S = d1d6a615340ccb1504625ab056d09a95f42836bbee98bbc1ebeeef5296adc55eb8159a5dccf5fbd9bab8854bdae4f9c73379881adfaeab1bed26a544f4b56067d1c29f473ad84486a4e48c51354e4b1a9c9ba1aa019d1c75c277a2dc5df6ec4e112312c93e5652dbe107270f02805250dc77e833637c65f2248e2834b7cb62135b43730a54e0782822fbceb33073912728dbe0da834342ff7d519404c1171b347b96a4df6bf794634247e4b15b93d7929a0e1852dd20b6c88b4f30e0a18be8da
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d06096086480165030402030500044027c454d298019b1b6718f4ebbb3e2d115f3ea8a214cc95367bbe80783dbc781438847c4b1508b6010de44f47ab6e213f32e7348b8e6d6b4f85fbfbd3b4c6e05f
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 73a012bce858e0ae42fa2893a0fb1439a73a9c101841b28ca8c8bdcb0c7b497853fefdef782dcda238a871bb218f1503ec8a52020c0d5d6887da7eab05c7c4f226c1f8321911cf966bde63251cf3e49ff8c38ba724aad027f876ddf10c2642a296f2eaccf38b4e5483a3e818bab0ebd574ed314989a27594a2a6c2e44b222b51
+S = 3a24d99406cb5a02ba7a403dc0b5b2bb87984a3feec115dfd4e5531993c391294aa226761a02affab891886acc356160bc9543f2b722412392dd5dfef65688d8084268278eb04482eee60f72a34b30376a8395f5f3fd27dd56e7a8431f2093a8ae93c02674409c492b52a1b0c53923672db546c85ce5e2e160c94e78a5d66dba5c398b97585a20f3b32ac35a4216e4b93fd85c3fc5693fff06eab4b9e0495c5ab0d93bbce6b3e16bcd9bb458b2d7b4e30f9f4a52f48311a26e3c0e9ae30e4872
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = af51ab7e521b64502702bd561e40dbb41e2f80afa95bd562bcdc67b3f6e36f86fd9256311e11782f33de2918ca64f5d083d02cffba209fc2667ca4a141ca60c02a7d4559c7add9696e6db9aa4659dec2a96e20bacd1ff8b1a4a48ad20096e383fbb97fdf96190e67a05877f4da461ef158b263c62a806b973cfc222f7b6e8037
+S = ac7598c1f1f9245d59b443cf44e1eaa00f9a213ba24fffe3b6051dd0d9f430669edeab9157371eeda529bace4e66f31f272b210b5b9308d0dda403385238d758de9d2099c516e39cba18a1552059d9eba6deca27db71e766ad67b9db321011b727619bb303df82bdbf029649300b03e0ebc3208b2ea8e290b670b2796b4ea12de9f07e6185fe508548d2516ee1f8997394079cabdb6bbda455983169fee7cca71eb4c5841c27c37762b985824134fea46bd2c95d7d82abb66894c6671ddc45d4
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = ab50f6312f99e068e4a76ed88efda9b0acf416b30500e798843673b1450be4ccf05f2f5746ba4ac7f9d5993ac15ca95aacf22085b676f42c9984dc79e63f0435554e05e859251442f88679b9da474474a0553b6877f916c1ec5aef830244f47181275f2e9263a8a289c2f89f0246e2c42f264ea27013b51e24bf9416c0a01a48
+S = 6c0b09fd6b371212279378f8e3d91a4861c63c7353e5480643774821ac72cb3519cfd77e46c6edcce92b796fdd5a511199e9b870087fd9d815e7d8c8deccfc7c229b93a038e202e60df022d0a966e6616c67a447cee59b0b3ca206e9e503e928dcb33160b9b21897e24d860c7327e83f15ca41449f7aea16a3e7d83faa458dd0f27117e68bc279367925a42ec8cef69cc1bae1df16408ca60b8f1b9fe9f837a1227153b59ab2b3707c1e5cffd79d7c11a31a81f41317f012b497e34d4b3bb962
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440c4765be0d27a4bdb86ec440bb5259aff46c9bd89a6870bf5b87c3755ce45d780c63282898f959c929d9f144143a038c36d4d0448ef8c4663cedf5cab3d59bf0aefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = d3d03ff14b9e72bef1c6e7d29a5bb8f0ce554cf3cc867a63cdd0f1468d94d738086db0be811f82d8c9ca36d5be64426b126585074ec4726216237155ae4782eebdca24c35114758624879ada1efa61651a692527edeaf30aa4e3eaba0e7be8b67b4e63a8c26594f28965db89c0065f066fc7f5fab2e143820179251cb5194fb9
+S = 81664625093bdfe332db62e3c1f5ba000062576d95f1a82dbc5043eaa267d7602c25cb45759ae8ceb360c017f9a0c4847763e25206699792af187294514bb214a453730350673bbf2feb73033a567d4d11a6a4a13d2d1d79850bd71e4ee9b8b404d2114f505ca695a760be6b1a784be63a208edeadbd1a22c86d8ba614210d9b01b89f70243749f5be9b43385ba94ba0797219323bb1817e5e3bfbae02e2e360383e333b27c32b6685e6b9545a3a6c7742a7e0612f20bfff18907c58f3fe671e
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 076fdcedd54168af223f18c42188c7c5860c5f03517b5b00f66159dad4115297752adf60e6e8d614347f9466b83ce96b88be4ee9bd999b19f1bb26d9ea7f01b84003a907584cf232730480a6bc9692a3cf5c47d40ff051dd133ec2353e0a8c4fb6b65b5ea82aba7686f2aca7edef2b7e824b4dff3a5cdf2aec1c726d8a3dce741605abe0a0b66047ff6e3e7a1be8338af56b4cecd1e650d4fc3c52f56f29e746c7b2ec95f9dbd6dfd1f822541fb6f331faefdc00a346e86b2dd6a88076894b91
+Msg = 4ff4d6aee37bbccf415b68228612f69eddea178398c0c13d7f0a258b6719e2e0079b780a0863ff115b6d1962cf1c252ce3c7b50bd87442e40be31f1082cfacbcc570cc8fef44998e040f563d8521a40742d7f9e070644f29fbd119d41e437bc8307dba87c1a5f20ee54b07fdd0a7ddf7a322cc4c86194ed5f7ddfb2061feb8cd
+S = 303e5f73eb2125488fed92692fe597994b86e4189ef71152bbe277501866f64df9de78f3d11d74c6aa48a916ce2759012ea86a862966a3cb78d8ac12d0d99d059e8cd56e83c0f5198ef7248059510687e3943fd41defcd58ad501976ec17fd1c252c13a177cb99d2ed831279d6cba8ca63ad0929eef4fcc85c985bc449030a76aff7a2b389d23b89471e21907043eb6c973ed375d85871bcc9203d6c615fa78a066e7fc5ac9f8f7099ac22d5a8b26d0608df22ae0cdbabeb81bc6f750a61f5ee
+SaltVal = 00
+Result = P
+
+n = d2b6c8fd44e7eb621fa6685fb62371872b5e8408af51bd1b44c6473823402418a26963b98e6fb191cf74175e64132ae6cd101133fc002a89c10bf7739eb930b9c067b52570842395657f927434aa3acbf3369dcdc3990f77cbf22939ddd5877f09c8aab818b80aa20544b6928fe62c78795a4160aecde6ab454db0dcdf1d6c13522526c5ccf82d429791059306f02cdc18c4e580ec6c2da19b3c6de63933ebeac79010c73df95748d987e96a0f8ad523b5014b33423f55922aec2ec23b9aa22f
+
+p = f260d143cff1e8e0931765da8cb335c0206bf7fd19aaf8ff41e762992f2bb0a660cd65f08a80fe502c9125166a6927aa1859a874159796fada835b48522f5795ed1f8d23f05016358ff908b0dd638bb7ed12c8b80b46aa858d52c77bb7fc0ed1
+
+q = de8e674fac0b7ea32d518a22030fd10d4298a77974db8febe195a4240dc5373e8161baf8ce47dc4fd076f64e307ea6262c35b9819bac4f142b613973eeb6a62a15a2ff09fba9ce4db7186969af925ee3acb7d3be7a1f9c85358216640fc1e0ff
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 5d7f76ed239a1a5d00c3a4f4da964ae0bc409c43ce9b147b859aeea617e8396532cc2fe1ed50c20cffa2772a2eba778f0b3de4aadda26942db9315009e96692ed5ecafbe3bb98e8ec666dcea2144b3535d72c77ee400f6a0ae5421e9b7cd3b4eb0a79f8cf41fa76abfd77a3e9a7b25b21aa5eec8cafee41c66a7bb6a4ad7d74f
+S = 810510f7e41b63d4d1db17ccd919547d021c0148047ae92fa3278a1fc7d2bcea796f6ad6b927df033302d5df46b3d33af70560c01bceb46502552a8b6b67e0c754ab1bf58f5ca9f96397aebd5d852c66865c399032bac358e7a990ed6dab9aec27e664a08c505fce3dca4bae2cefd8e1b35f6d4b4216cd6572f139e4b520188e8199c9e3809938ad642123c466e0d59b172217ad290dbf74e2ada78c0b7dfe639ee88caf44535a734794406fe909922442b1bcee8fa3a8e31bfd665dd219c46d
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414fe4eed9d60746feb5599bdcf486716a6a04a0e69
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 044138280eb07cf03ec9747c7e9b89e0a37850b2fc40ba6b2ae38b1132210d13d194057510f1e62c178b45cc46188d6082b8f499cd33ad2c1a825f755f92d760eb44fa89fab8fda287cbd81661def7eb81da33ed9b700209f3a6eaf7728f3c1cf959feaef58e2919349315a1f775314948e4f7f48d801fcb5e5413de94a0a40e
+S = 6af0c3b45ee0b0f5182b692d5703921e779bcc5ec5e5f71fef5c480a491acd10e61166ac2b40e4246fcb28aeb5b8feb870be4a4efa13695ec211e5f603d86d33b228a41069003d18841f48aee2f4802f1dfe95caa9a3d89e5425ce06fa4d17ac2e5fe4af0e5a2f86e5ccfa21c5d1520290b2d4d4ca5096486b6012e302b2eb3cd9f906d36719f3a19e3c124969eaad2a43c2e30bea835dcad93ed550dc3137e59fd891694274cfd6a2522600c661dc496f4e4de5a58aa51afc15834de5c97e96
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 8f662067a26e81165e23ed70b145725faf2c591491ba4d9ffe8fbfbc8a7b88f07d39d0d5d55a2fb28e7f134f20cb62084a98601f0e69d257fd2064beb47248caa79720a71d461ed07ce069ddc7ecc39b65c36a62248c3ba37d6b1dc11af69d2295e9d685831a9496b1afb9bfad8edf4288153e85db0cd0ac08d7b46dc2f0d120
+S = af16b7a53f57ef673aeaf9a17727836d00e883352e7e2109911dd839ab23d46400f140af84d4cb4a5864165c682aa85eeaf4300e74b94b4f8fdbadbec540e07056b55fffc96a627939928ce5fb61e119c94f14719a93fd5f3a3dd4a8754a8bcaba64afd5e63bea1a793d420a2b6975603f2d4597b26799da0240fdb7d8b0e6e2896f63bbb46526a2f651ed17deda3ab3b43622e749bb608c6d30d41d7346f9338bbd768209e531a17e2a92b815efd222049451785565117f39812de4c6ecc65e
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = f93d6cdebcf190ea6ab2358636af5cfe4b3a9bdc1bce160bf350aa3cd3956b897e255158cd3e2e83481ce3b6f778d418764f992d48e4f7fb6d080e6b3799d3f35949c17241a0cc5ba84597166779e6a38ce45681ad944cce7c432baf9cd8caf2b33125f2c12052bbb0b3b76f2cb97be9b4813a9ff1e5fdcd478769d0ab5b36cf
+S = 1e076b3feeb281e5ded58a886f653c59a31789050df263bf06401eabf4eb79b4b516350fa63b06c4ea8339190ee9ec30c3972f0009a892bc5938e17c0ad3502f5b6ebfc6e90281cdd94ee5758a2747e05d2523ba337301d392bfc6fe57890234bb1e485ecb0c2eff55c6861100b2911fe594e6db29ed773da026bea1875f334a2de2214e656f6bb25b6f84ef5cfd4158d27642f84579c1f5e185bfbe2948c2ef26e6610355e190b4c06143f487a68ff15da2f7acc9e28bbae89e9ef0c362d63a
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 6f856225ba8dd27718b7c684764f2a18c19df4dc4bb9accd71a12bec7b89a337c372dfd91afecc9e678339a9915edb699f8a94c91e71f4a7c30101885203338abea8c39a926526e68f01d49597ed4db6cad35e77ee71a09814a8431f78d0094caa4f95cfeb6ae639da5b1fb150a389e888a1da4f8364b887aabe7918b6992d67
+S = 2491418adaa343b655e7a3e762737b02ee904d6d79fb6ddb9cf2043b671de59e5165f2898bace269f0e65f3e754aee71a5fa596a5a89574afa49818c7a962c38e1577f2302b75ddf53fff93ef035be0dfe14a086a27ab5a2e64808c9abc9007cfc748fac383c9c89fad72d89044c49cca11cf761d7d8e506920aeba7e7e8f187aa287c6c8878a90fbded8489789e2742a8386d8cb21f9d0b51123a5f78de74656107e562ebf50ace92da2437ed325629e66e14b573668ed6462a8ea21e54a543
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414753938c49eb8f7bc120354dd8ff2177dbe9bb916efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 9fc80458af5f2489a910779f7b9d078b249a68a276219af01ac830d0d4d0b2ba089f415b7e7079eb624a9cbb8f2eec0d0d955829d71a5bade27322255ca5eddb3178b7f1d42919ac3c606c132d612eb9b886a6d705edcb9d506e63ca32d0687b223caf403bf1cc75403a30d0dd9d94362f569bd38704b2696ba13be8deb7ec40
+S = b23c38a05b861aabb41227c23af9d3b6e1767605cdcaf1627875a7ce09f99cc4b7397a4f010a3bb2d8a9c9765b9877f936369d761a13dc3c22c0db84a3364661b5c7fd39e6965e43a728069daf89612dd8dec3dc9142d6987b8345579d9be7891d315247955f70ba789d3650947de9e92948e049696a00d0e0f6d256cfa24128be180ead9af648436c1cd21d0b396d70c27c94ad8c8625b6b3dffbb3ff78c475732203c8d08a3f99e7dcc86f1c233131571210e8135a29565761dc94e77bf484
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 5d7f76ed239a1a5d00c3a4f4da964ae0bc409c43ce9b147b859aeea617e8396532cc2fe1ed50c20cffa2772a2eba778f0b3de4aadda26942db9315009e96692ed5ecafbe3bb98e8ec666dcea2144b3535d72c77ee400f6a0ae5421e9b7cd3b4eb0a79f8cf41fa76abfd77a3e9a7b25b21aa5eec8cafee41c66a7bb6a4ad7d74f
+S = d1b5a7c9880f3b076d635ce4f881de6c715d0e2ac85fd08ad5d4ca93f2b04870f7264bad5c7dc9f38046b7ce0bbb4fb4e6279571533f61cde6d540c6e6bf69e4869ab76a563f30cc6718cdef849f76c75aea4c9a3068bc579b1104474d9a4849d9c3db49fee17afa5281fa7ffb848e9b33835e942e89c04e291d123f5d2bc5869f076b550dd8c04d2c2f29ad290ae294ab3d34ef54f5148b256f50c54f14dbe4f02e2aef97e39a90431b774142b3dbaae385615323badf58f309e70a1084ee59
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c7c8aa165fbd14e4361a3bdf3f9b6bbfcbc8e14153c901f8e2104975b
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 044138280eb07cf03ec9747c7e9b89e0a37850b2fc40ba6b2ae38b1132210d13d194057510f1e62c178b45cc46188d6082b8f499cd33ad2c1a825f755f92d760eb44fa89fab8fda287cbd81661def7eb81da33ed9b700209f3a6eaf7728f3c1cf959feaef58e2919349315a1f775314948e4f7f48d801fcb5e5413de94a0a40e
+S = 6883e11e659c46bbbe5a9b3470adfcfeb546bf008d1f2f272e2b3b957ffb52f6d25e0a1aa4facdde72c103566cb6b898a9f059f17b895ccca14aff8a658591998e8f106dc8624a48158e932034f9f3fd4f2692e37ab8a31d02831641d0518d4557f2588f394eac4a54510b4d4397cca2f55e7b8e08f7fbcee8a9f1c60e4f6a8fbe30b3b29bd7492aea116701187d6bcc9c91979de68b52e7c6d57e4fb9d5fd6526497be575ee861bb83e05f5b51b9cd60276d93e6fe987f4240c610d94aedb49
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 8f662067a26e81165e23ed70b145725faf2c591491ba4d9ffe8fbfbc8a7b88f07d39d0d5d55a2fb28e7f134f20cb62084a98601f0e69d257fd2064beb47248caa79720a71d461ed07ce069ddc7ecc39b65c36a62248c3ba37d6b1dc11af69d2295e9d685831a9496b1afb9bfad8edf4288153e85db0cd0ac08d7b46dc2f0d120
+S = 0e53008d7626ce138c6aff6c40eb86dece247e192bd5013880e759f96142d22d18abb6f1701b88aa28d53b0c5c13b91a316e79373a37ecfcd61df7d3c34b59ea36eebe0c6864ef63514e504a8c796780be8c2586f1a2eca3a45d45b15c4c38f94420ef563efd9fe2d8c194d01c7c34cdbd7f89923bb39bec9e8ddbb1a282e1ee18bc9cc93ab42c2dbe58ff0927036d2a66e364d88354571b75fd11f131076d6fc9c75b810b522d2c18faa4a6332cf82122dfdd17f5efa030fbb50177f97c9bf9
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = f93d6cdebcf190ea6ab2358636af5cfe4b3a9bdc1bce160bf350aa3cd3956b897e255158cd3e2e83481ce3b6f778d418764f992d48e4f7fb6d080e6b3799d3f35949c17241a0cc5ba84597166779e6a38ce45681ad944cce7c432baf9cd8caf2b33125f2c12052bbb0b3b76f2cb97be9b4813a9ff1e5fdcd478769d0ab5b36cf
+S = ca58ea0da7afc7dd4a1d32ff168a03b478f296dc0f6edb2a0e859d85476f1af70d21b42f0af6fed26cf82604f8a2c5d87b50e5a5babed6d585a6a84861ae56dd2654c4884af6672ef57c63d8b03e5d7cb8ea49e6e8b53051cc64b366dab0b93fe29dfbcd7b9a0b8885711bd103844532f08ddc2edea7076e36e7ee25eb592bda6a4f862af008344117f5c51073407a8d230f2ab5aad9c981ad10842706b502f4c984f2f969dfb5090678b602b4748004984fec3a39779c2f5ee1b02c6eb77dcc
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 6f856225ba8dd27718b7c684764f2a18c19df4dc4bb9accd71a12bec7b89a337c372dfd91afecc9e678339a9915edb699f8a94c91e71f4a7c30101885203338abea8c39a926526e68f01d49597ed4db6cad35e77ee71a09814a8431f78d0094caa4f95cfeb6ae639da5b1fb150a389e888a1da4f8364b887aabe7918b6992d67
+S = 1a524bd769380e63ba31ebc0adf908a5c2b657b03a534da42eae48f044ecd2bb643f2ab320b34df4ad0938e17044d9e8a40c0b50d696024e0f717f19102f82854c626642da58c430ac865d3a25299f5d8864b418a172b331734db2efec8e44d082556d7d37731e4d4a317a22a076caf9f9e9854c1eafbdd57fae1822ab268076126f55c3ca52873885f9be15c0308210465b78e34335d6fcc569c8e4ae0f65034c0d8ffc1f078983e15e4b2bd7f46a0bf41c8ad7fbae341037c2bc87c2248060
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c3634827aefd0d0bef3df495c39e6d596907496b91679e2bd96be6542efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 95d3ac5ad05aabd72a1c331b0bb6f75ddeaef4f4b0b6a6bdf92f7bbdb9ed8807c73a7ae0661dd0221adc48debabf9745c5175dc9f97f587f2262d8c831bd73308d26f996ae0eab8ee743a70383b8a7211489eb71083a74467d40735957c201b08fa010c4cdb5a2e23a5939d28f2a8eb7730d8536036f61dab2d134b753839a4e
+S = 15893719e5cd0ceaac13914028cbc46bcfa00171d18041371ee945c546f10a0f212231090f4ab7f490ac852bec6ba820997d71467b797ff9a09af565794a85c15e3c10aac19b91f6a540afcfeca49f1660a788c2ae040a907146b4f6179d808f96da06f15daa18cb3be6b2ca0913fa91e966652a29360dc41e50c6c43ea5d633532d264b0ca09987ff3b0cd1542b4a6a48332d434ee3f02f9e0ee353d2acf260a3ac278de0ba65677b44911ec76071f74a5ebfeb33107a01fdfecbbc4645baf6
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 0b9c18c93a8b1b8fbbd036c2d5a6869c2c326e80e613df300d3ad74034fc28cb5e657b641bd0944ff4b4d8f209c10c86f92c5f120247ab9a6a54f8931d9b429b97ba7c67043dd4fda66e3923786e1a1711857180cab701a52398dbdd636127467f4221ba3dfa62ff99a6613e68d639b73be6adb2868c69b902ad8a044f756135
+S = 29dff9f009373438341a72589399904fab9b900a2bc65c371c989dd60e9c825dc222d982d773cea97be3a3c378956a91240b23eb59a4cd5b78d44fb948bc402db68a8efc3d9d7c48b55a826bab47ef4b605c0ff33a7019d8f1e71a17b43a6a72a57889157c15d10d65152a7581b8ccc0c09b1dd284d9da78786853bb8b88f4458bf178e05247713ed13a6bb7080827a1f4cc85de9a8b094f9c6edb71e8e3166d4907b786fc64d97359907661b6e63e6c1e415e9d31aff0e43a47e5830fcbd26e
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 5c27ae4e00a9253b8e43c744e235654a6ff72a1cd37acfe0aeb10fb5b5505b9602d4ce81aec363d9a235660aaa93286bcc9ff768d7b44de03e4f48cc27cf5a22c07942f9d2bf3bed98c273c5d115be5314c48c9c64951939048de3fd8cb661d83d20f2fb9226143d17f2d6be7e4490caf06ed100a1a499b3a772c8900c8ed781
+S = 36b438a2420cd0683b040001f926e499992d21be6d6315302123efc80d63d9182f014fc8e8cbbaa70c5875f2e7e7127e5925eb267948101ecca130bf0846f2c4aec394faedba13ec6cc19e476cb31c2cb025bb188127fe70d240fed47d674f2d5b2c3b4660b08242ebb5c005bd1e836c908121f0e73dd80a18668b79d05783c521d9913768296b057cdad7f408394d080e46b74e72c6d337b54c6ff976af2eacd7ce51f3d2432f3ccf7b55b074cc2817272816525b91264c96325f3145324cea
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420cb6adea7aa43ed6220f5f0c4dce57facddc4f77cd4e9072b0468da9bf104c1bbefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 8bbcc23dd3ea4ba9c1d1c8e052be5d49e1f358c657050a3b9e83d64a59d88761d273e6f733258d12facaf60da72bd798b723b200d601a7b1512e8ef9ca10420e2f2d3f53ed9470d76079421e8e1ffd2516fb54a063163b8625b3f8cf02327d7d8834f5d967009dffdd25d59c716177f7e4c2672e650b6bc204593d566906dfb4
+S = 3e116c20ca4dba97fd0804d5ac89cf75bf53a71c77af12c2301a1c093aa269a9074f467c57727a5c0b17f18968842f98bb11d8b4afa9a9ba193c0e8f2d2853a19293c310ad2a5e792ceafdf307959a50fc48aba8dd911b367614b26b1a19ef13e37a4e3eedd4229174d7e6184f6bdc4c5d24397545709170a72fe202bfac3695373da28abf90aa1dec9ce1ecf4afa22016c2b6b65e65a5ffe38925ebebe49e4def0133916b4c22d2225122e1d77703a716da7cacdb85d9863d53c039da1a1c44
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 676a410de221dc39a833bd94dffc5b06dc4ae2613b1ce1452ea9434115a4813a4fbf1611506e3280f4edb24513845083560a176549a81b04b1df668b1fcc3599c5ab65e6899b282a58a0fc3abdeede74b265ba5eb658278a1f9251bdb29b364f713716d5b43024fe7b5582bb03c36ca39763b495a9b46e9f21cbec1ef598ed27
+S = 34f5337351298d299f64828163e2c8edca0bbb1e80d8da4141c3aadd5827d815f32ec5ec6696679580f92d1e97ea7cb85485566f061a4eca830c22f01f9d952d33c2aea8cf7d1b49d426cfe029f2c52a2789e9031e015ad74c7105d43b9fa603869e850c6be898830ce1a921430cede5f1312de7bdd4edcde835f32102ec28628ca49b5009fdb5ac03c6ad077c77f66fae2779eace6908c4fb5051d82255e7e50920afd1692f1c08d61d233f47e8a7a1e342d39fbc8ac527d96a622a2812f177
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = ad82f5bc35d0995edf617b3b05f4ebabb0444cdb678980734541a1754f30f26804a615b735007e54167127a09603858fecd8bc0772b60f8ab7c39a15cf8c4348ee4ceec6366cf0dfcc46c66d312e08fbd0b3982dd3221f5c3b4cba803089f05395fde8b3e01ad8482966c168807f5a37845c491332d5992ffa66697d1830e1d2
+S = 8dfd4ce88f22ca5c7faee59e9c0c319ce22581108d1f333a4f53c239a840db6cbd9a18d1be3d211bb2a7dc69d1750aed173a50cce78d4b8ae804525f5e3dee05c98d9e1debef27ac43dbd8faf87607affdd97589995cf062c7f3b5c1ce7dad7c200c3124fdfce5f05e0044ea952e54ab642c47e0bff3f80cf96f0dcd08baabd11152b8741d8e700c27d805ee6edff11f95b441a24d65bccdc6949b91baebfaf249762f61593974813bec018929b51cdaa89df092b38422e2a82aa7cc8a22f971
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 75025b7ff7978e537b49fdbc59a54ce3e8313c96885ecce3e6b8a5e67b60b4df56bc19871c6d40a54d814ddcc8eabec7922f4b48d362111c2152f0b30101323fab596d0c0e1aaa0f1417c6c127a2192ef44556486fb3b28217fd499a7b09bdb6fd4120b3d68814ba5a7230147db4a63f97d923416437f73c4f227643f05f9e6c
+S = 1f435cd0b2835f4a895c2a53c4a9cf8561197c90548881f3150b7f2247ce7c1f0fba20dc1b3a265566b2cacd6ac66f087ccbe11776168f382ca2cf79cf97420ea665c5cc547e250a3582febaebf9b4ec97a1cf7c8f1f75e75e67454bb2179d6fe1a66a1ca01091134871f8886eda7e72536eb05b3ab352f8e775f94a0c1c3060d3932200cc10aa07a282a2c540ead4be9c3b664da3adbc4a513e5363b41e8e867d2c348eaf50c37cab0a1ad9f7e32dc48f1ed90d2c4fd88c7588f3250e9b582a
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d0609608648016503040201050004201652a7df9a92d3bca639e5b379b1bad5728d06fe2ef755fa734a1f09be6e782c
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 0b9c18c93a8b1b8fbbd036c2d5a6869c2c326e80e613df300d3ad74034fc28cb5e657b641bd0944ff4b4d8f209c10c86f92c5f120247ab9a6a54f8931d9b429b97ba7c67043dd4fda66e3923786e1a1711857180cab701a52398dbdd636127467f4221ba3dfa62ff99a6613e68d639b73be6adb2868c69b902ad8a044f756135
+S = 49eac9a68c0786ced77b437b01a3a562a5d6e6fbc9728dd513814cbe611f3d1d4aeb4540a61853595964d370406f3a18fc6973387c99821c8e966c47bb6e636543ba7940b1c0f23a8fcf46ee4e3173dd39980088b0fb2479ee4a08b41b2dff7b3ec1d2989bae39f7abd1bffc8d33155518ea6968b6b471c90e6773c76c6fe8cbb1fcc138dbd48e9eda1090ab245dc2b98fd7c553a7bf11321ef7c77fb14f36e5b7c969abd5e8c049d2ee4fc3f08caa6d996ee0580af6cbe27c2fb1e0bf3d79fd
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 5c27ae4e00a9253b8e43c744e235654a6ff72a1cd37acfe0aeb10fb5b5505b9602d4ce81aec363d9a235660aaa93286bcc9ff768d7b44de03e4f48cc27cf5a22c07942f9d2bf3bed98c273c5d115be5314c48c9c64951939048de3fd8cb661d83d20f2fb9226143d17f2d6be7e4490caf06ed100a1a499b3a772c8900c8ed781
+S = 2a7d47940bef4582f4edaaaab4b0181c76c091179465ec3c007edef88775986ac07f85b4fbbd68450ba9dc346f590cee4ec1e828978d82c5e0bbb87df6f8c548ebbe64fb4f101bb8cce618d88dfb96f3d8d5efb0d6f7dd67c8f75eb068005f47db66d87c33b833dabf7dbd02b3b327988164f436a0e313efa3cd124f87730b463962b21b5a4e3a9530db7ea0ad8d3ebaa23414aecd343ceb58e324a1deb1653e792ec5a9eae709d77b2e55b6e8b5f653a8044882d020f5fa8520afa588416d67
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430e1d3f55e005049c7d99593b81a02de751db47deb6bbd6cebef963164123fce991214c8be6828cd6caa14964f293e1245efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 8bbcc23dd3ea4ba9c1d1c8e052be5d49e1f358c657050a3b9e83d64a59d88761d273e6f733258d12facaf60da72bd798b723b200d601a7b1512e8ef9ca10420e2f2d3f53ed9470d76079421e8e1ffd2516fb54a063163b8625b3f8cf02327d7d8834f5d967009dffdd25d59c716177f7e4c2672e650b6bc204593d566906dfb4
+S = cc5bb97aff280fed4499d2fb96d5acdee24406fd1d80217a0b6a27f7324f4728db0a4a6f996addb55ee8fd2fff1aa109d7293f5a7954a08857e53941d1ba0a86e1c38ec61cf9d54c2ed40c281475fd68dfa1aaf0c246a05959465c89bef974df66fb1f3228e07fe03eb7b9546c6f09dabecc6f2b8f2f6be058186578d87a097aa6a0a15f98061d4d1a1ccb67a9a6ae6b35e264e591a8115b459dd392d3c1f6a6785ed3c97d319d19b562da148e7361ee261c2991ca09ea924d69d5dc59f7beae
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 676a410de221dc39a833bd94dffc5b06dc4ae2613b1ce1452ea9434115a4813a4fbf1611506e3280f4edb24513845083560a176549a81b04b1df668b1fcc3599c5ab65e6899b282a58a0fc3abdeede74b265ba5eb658278a1f9251bdb29b364f713716d5b43024fe7b5582bb03c36ca39763b495a9b46e9f21cbec1ef598ed27
+S = 4f43d98e1a988f7b64d37fb9db79b1759e1b971f90fccd542d636f04c4f8e35c3f07d941c906f8fb788cfdef25b4438a5c9322ca2230e62b17e618dcd7a4669a187506dbd2087cd25da81f351cb87430163208dd06bc3e5b7a36559969ebbde2200f8933c45cb327f5e56e1c36bd15d11ebc7bd0034cc2fec3a9382dacd61a715c1f2f5babbd549faf752d4515e4375df0aae487327b765b45e82a868dc7985e03bbf1e6c80d022562c7e4455db4463f42fca3f2bfbe9f6cabeb3bb61fe0c073
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = ad82f5bc35d0995edf617b3b05f4ebabb0444cdb678980734541a1754f30f26804a615b735007e54167127a09603858fecd8bc0772b60f8ab7c39a15cf8c4348ee4ceec6366cf0dfcc46c66d312e08fbd0b3982dd3221f5c3b4cba803089f05395fde8b3e01ad8482966c168807f5a37845c491332d5992ffa66697d1830e1d2
+S = 5028c5c1d6558214048ab00458a5b0308053d91b312c671a15a47ebc32dc85b9760202b7f1d81549fe4c76d48318655b376e7d2398be7693f530bc28611cd48a7825759641c24fef6af1376d0d7bbbf23b9753dccb810a95e4d988be0c3c694f445f47e46e2aed98223c0583fac02cd9330e5652a697b07338193efe9afe1a514786c31edea49654d90d87d7caf26978accd08aa2272e12dcb058296c032fae8c63c736bcf4837c1d0bd2deb0a9539eea5f376aa5d1593afd8a0bb48d44bd5a3
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 75025b7ff7978e537b49fdbc59a54ce3e8313c96885ecce3e6b8a5e67b60b4df56bc19871c6d40a54d814ddcc8eabec7922f4b48d362111c2152f0b30101323fab596d0c0e1aaa0f1417c6c127a2192ef44556486fb3b28217fd499a7b09bdb6fd4120b3d68814ba5a7230147db4a63f97d923416437f73c4f227643f05f9e6c
+S = 068559fc0164a646aa07337ac8d98cba1da106d4fa951f408315284f4b2138037687b87c33b38d0e180ccd62bfe1baf2c42f72b9750d133502092c42a3faec6e42f3059ccb5cf1b3db1ec2c714e12aa0c5ab612a4d0c913ada82c98015ec761e7237087e2da676cc92e3340b2f31b13b157bb128b2a6afbd183dd67d5e1bf8bd041e580ac6a3fb8b4ab280d182ef906fb247c0d174076da4770eb10b13163c2e53f0a5b8a0b2352de761677a424fd5d71a4efb54b49ba6e2a96b9aa740453157
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430d7d7bfdf4dd5cfd15b04f924d4be54564e72e6a2ec5cd83b24866b42a01970acc7686ba35e3f9fc29f0fd53fc5254104
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 0b9c18c93a8b1b8fbbd036c2d5a6869c2c326e80e613df300d3ad74034fc28cb5e657b641bd0944ff4b4d8f209c10c86f92c5f120247ab9a6a54f8931d9b429b97ba7c67043dd4fda66e3923786e1a1711857180cab701a52398dbdd636127467f4221ba3dfa62ff99a6613e68d639b73be6adb2868c69b902ad8a044f756135
+S = 3583422f69bf11bb8c8c9e18c40cf2fe3d6930b174a4d8efcca214550b525f7d460077d280e714b8297378a9d228226c719f790961999f0532d7068ac8d51dacfae64819e8b7eaf618ddbc33557cd8f9a3a1e65efe8a4d02654bc725b1aa779ba54b1b9445488a084b9614d8e2c9a0d559a217c6427cb62a6cd8a255512bbdb006427db49b1a3698b643a21d65cfea8e624aefd38f0a3700687bd035028bc161f5eb005cb66aed2fe59110108140b15d6b97567b72b1c712d6fd030872d50ae4
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 5c27ae4e00a9253b8e43c744e235654a6ff72a1cd37acfe0aeb10fb5b5505b9602d4ce81aec363d9a235660aaa93286bcc9ff768d7b44de03e4f48cc27cf5a22c07942f9d2bf3bed98c273c5d115be5314c48c9c64951939048de3fd8cb661d83d20f2fb9226143d17f2d6be7e4490caf06ed100a1a499b3a772c8900c8ed781
+S = ac97f3f6ebcaeb77a23ca3b9226f7167c7315e5687391b700f21e45a00b23d7ad5834ef313eb3163b2390ccc63f9d76274120c1f0380747b33c1c77edb3e06923482e39b5c964f8499c20e28ed3fb064990190cffd033ce3ae384c275298367baafafc5e66bb0cdbad6e2cf9b16a393610f0088c129b75b88da6207bfb8570425e38b9f2a30d24f4753184e36ce0dde7e9026fcee5cb88f70c1bfd3b9a3f0a0c6bb80a04266c2edb3ca9c06a37cbbf77c1b50c01443c9282d023309a1668fccc
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d06096086480165030402030500044068ac2dc5d380018cb50e8316dea0bd72d31a9c354b9185b1d227c6540be123d48d79581880a02e2cbb7166289ab6798fd3215b272fd171bf16f74af65de4a360efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 8bbcc23dd3ea4ba9c1d1c8e052be5d49e1f358c657050a3b9e83d64a59d88761d273e6f733258d12facaf60da72bd798b723b200d601a7b1512e8ef9ca10420e2f2d3f53ed9470d76079421e8e1ffd2516fb54a063163b8625b3f8cf02327d7d8834f5d967009dffdd25d59c716177f7e4c2672e650b6bc204593d566906dfb4
+S = 5b591910bacd2f0bb6b2052f81445397d2056d114924a306a2b24c4fac2b7698d9ad725cec3010d57b11795f7654969a86f528709655d07a336a68fd4cbbe6ffc95fbf1a6e6c17c2d627c6011e4209f406ae7f2c670ecf4081053c2283845e2c855938da5530a146a1ce4bc203d0179a19398177534c7bb37cd9837911e8b1e7988b800e8046864fbf95e8c584a3c4209f3ea5fd535ba58859ff128fed9d0fc5be8e8c2890a71e38f3acf2a1fb537cdc87f53e3376276c8cd501d21069e453c6
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 676a410de221dc39a833bd94dffc5b06dc4ae2613b1ce1452ea9434115a4813a4fbf1611506e3280f4edb24513845083560a176549a81b04b1df668b1fcc3599c5ab65e6899b282a58a0fc3abdeede74b265ba5eb658278a1f9251bdb29b364f713716d5b43024fe7b5582bb03c36ca39763b495a9b46e9f21cbec1ef598ed27
+S = 5f6b11ef4b5b0a1bcd9cdb2086c60db19544dd33aac813ff6ec628d9de0ab882bab6496b79477cd445f71686f666b9e041e2ac40959ad94d3df00b1ef8c7ac3ab68b1d2e07294b3aa54bbcc1039b90dda11bce3aaf66646d19a7224028dbe7b48dbb67dece2812a5bf82e89db0908cb26043b78ca5ba455ab680d3d6aa4bd1682b39b5ff744a65dd5cfa909d1b71218a48d88e4e112a8b959b1886d956610d915ef41b30031eb3f2acf7d42387db245d84ada17b5995711ab2e12b8ffca81905
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = b17ebdbb8027c2ef5e5de76780979c65723d73c0ff0227d95074ded158d1abf96f1d578a3c716197d996433f32d3f727ae02ba2812e91044a2c808df892fc12b7a122de5981f153f934f5d1d14bc8a835cb2814e28089123d7b1b4a6ce8e12ec1c86c7325ad9e6cfd5b1be67f0fb5c62c374519c0807b55e38566b8ef197a722
+S = 1e80b47f34629c79b612fa8d25483056d1475f5f51c50ac60e8f5eade21469dce676d13b32140760d828dece21cd9aa2381b40f42e8e20a77392713f5372d1e87fc131eb7367b98d92a76e5276bfd073d6e44f8e9cf81e175d531e6ad50dbf84bcbb636b378c3342ddf6b2d85c3d27b2afe449c40f2915515c4c417a633b4de6c30e86f49f8f5dc44427642aa0c98e499e321aebda279a7321836a3cb24ee90c08c9e88f7745c19deb0e1de72b4da5734bb137414f1d4b1c78a9c2e58f148105
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0e0c2f8859ed53f57993a08eea025ce6e0c208cd61057301d1628d4802599c01a46d6d0c5ed43f09b87f34c206abf1cb1ebccdf2662224f81defbb29d761adea4006e9f16de6ad09f5b32be59d1c6a51dd03a41ec8c5eff6eb768b481fdb0908591f902492fb603537ca6292888ae060bd38e8a9355a175113522d7993584d142998ef52f6add24f1b5e76031844d322ec03914d8c7a26e7a38e63cf99164313eafca2709f1107a6c57f5d49913d20b3bd8c2dc850db453c3a23b00f18ca724b
+Msg = 212bd005a8e8e13b0bf4620ce2d3d6bbf18b3d195b05e90412b78d2e92809720cfd3bf7e6b18e08c2d4f07f1aff7cabb562edca48719de931886776605d0a6ef6503573c9c41351cd165c0dea3e59f5c17fd3739d50a7c66953407ebd44f6ae4cb03c0c9a12b88f3e07cb35c2667fba71d407760ac9f6c846f07674465c58806
+S = 6db765c50f9ac9da75eafad6652ddb99e62234397fb2c96769af84da59cd408c12b7562104d9ce9e7455e06abd53af83da43406c64bf15d37ead519d6b3a12cd5e02803c92eeeff2312cc681d53b22caafe9ed5541db754772fcfff3ae53cf67d07b8eda85202a36db8cc01fad12dc3b455bbe123f9ed7c3873c0ebf25bcd55dac7002c7ad1d00eee91c58c357276cce875ba1719b2356ad821d278e9a62ae1a6e22b145ce2c072a1faaaaa8ad2ca4ca807eba3d420af2f3d915993d1327c940
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d0609608648016503040203050004404be226f7beb9c592f2429b00af0b7dd3de42b17313c58ab7ff24fb441e6e47280fa6f5ebf3bc14dc60f8754db42c984e4bc5077fa7b559d727938c3043453166
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+n = d2b6c8fd44e7eb621fa6685fb62371872b5e8408af51bd1b44c6473823402418a26963b98e6fb191cf74175e64132ae6cd101133fc002a89c10bf7739eb930b9c067b52570842395657f927434aa3acbf3369dcdc3990f77cbf22939ddd5877f09c8aab818b80aa20544b6928fe62c78795a4160aecde6ab454db0dcdf1d6c13522526c5ccf82d429791059306f02cdc18c4e580ec6c2da19b3c6de63933ebeac79010c73df95748d987e96a0f8ad523b5014b33423f55922aec2ec23b9aa22f
+
+p = f260d143cff1e8e0931765da8cb335c0206bf7fd19aaf8ff41e762992f2bb0a660cd65f08a80fe502c9125166a6927aa1859a874159796fada835b48522f5795ed1f8d23f05016358ff908b0dd638bb7ed12c8b80b46aa858d52c77bb7fc0ed1
+
+q = de8e674fac0b7ea32d518a22030fd10d4298a77974db8febe195a4240dc5373e8161baf8ce47dc4fd076f64e307ea6262c35b9819bac4f142b613973eeb6a62a15a2ff09fba9ce4db7186969af925ee3acb7d3be7a1f9c85358216640fc1e0ff
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 34d9afccc659c8f438830b2fbe8b6600dfabc007cb22e826ee7dcbe2c515eb0cf1d90ca08a4d30edb5d3c6f6792a1f19ce3421eef7fc3f7212f7a965ee8abff01ccdcc8b498ff11ecb9a5f667937c99bc0f51a50f3a7639ae3ac1774b0737a62de3d5755ab25f1cfa05e3d4767bd4ecfdc7711f4662b3ae688237ed9b3d703aa
+S = 38fae4b9233682065387c11829b0a9747217bd7d49acbb5957b8e7d231235f4f7ec316b5a3e5f4f8f45c8b9a161f9b8d3bed9aec0a7b0d4484474150c8bdf392172592c1d0b8ee2724d08aa73a32afad3dad1a0cac3a9f21811f53c69809239c26e36c7b6f4b3a90dceab045413dc3e89fa1927cc7a622e55044a3417b44ff93b2faa3c864c6fe519fa1a8189121a4881e178979096f17519203f0d2c9313a70b2a5b670b675319ad0971a0728f0db729fb5d50280a33fa201271715b256515f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 95e2657996a4fa69f824ca49ab5a7e6ebaf498a0dc9eaa7f4981c51fcc0935f619ec6bf862683b0025cc48724839bc1e67aa3c686d321ba66185cdca83ba9f41984fa61b826ef56b136e13f1239dadf6e03d877866ccb887908917ef0d33f117b614fd291e3e91736b15150e650db9bdcdb56317f0f5ebe97c938bd691fc9140
+S = 3ae81b95c93a702dada5637e1c4113e5c37a8a24021bb2371c788a90ce8fab1c063c7e17f7f570a25baa9adfc78035d8ecc87219df1bd30c6b8b593682f354db71902ce23faa18f4af6fb9cf925ef7916c168f7298d56c49b6c68da954b56e2164ca37bb7c06498d6ee96aa502011356fc48733b937f299616ecba6699fb8d3d64e332c0fe3f9c58c18f033f92f237940afe9101702af51d3cc220547028eeca8e2d4f46ccb400f0620339b4da7d415ea288bbd7552eef2e68e4ca7c4ea6d011
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 24b78a630dd8cde2fa183956b3edff7e0ea5bdcdc0f1f51172a3bf5218b7bafd7e9048422385fbba4b9c4a4d50958953392b18f98d96dae66a54e81fd12987284465586d9365cfe0f35ce6e250541367e46f77550973582e4b85d1efc235c8389fbb21ac0480319b19e176df5c2f850338fa43abda8f582f40bfe18a92e26573
+S = af9d6db0d610643147996ceb4e3cd539603b068b02eb31a70dd83d40d45f88ba25edda65873271099965fe67758104c2e40b93a8aa3eaf1277fe0d0db1c08de0b96b82c9b48f9a2cac852124de8ff81a7d9742365c8e7f68e94b5d3fbd3aca0e42528b0693f4c61aad95cd912a53545a785e08464b2f675a4b1a5a3c53a8acfebcb25875f7afd802f6f5d6342b1bef4c848504b40a475e56ce9b967175dd9288761599946838617dcc57ee43e1b99eb47be11773cd326029cebed368f821fd4d
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414a651b5b5a63ddcb4142c5f673fff0619b853c194
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 165c3a41385c453b38d0ce2eef3a1fd2863535b993080c84847b1d5641ea24890d9726a0ad44b37dcd0269d59f44b9e0c537ee5571566a95cb39332693adaf64070aac7307c1a37877353e09e5cc17e26b45c3d9d74c0f140a4b89799e844366cc5dd3a28cfa9e94fd1157b308fac23e4006be2d0d1282670a5c2735ab9567f7
+S = 56965ebb90a59710f86a5868573132bc39e3be28d7b5c1e588bc2c80799a0c89c17dff65d281b7aad6c0c4dedc4c134d022512b3821e057f51e27105858b2ae063f3cd0b4204b326ef8ba52310a3187a2effb3295a848de5d06d73504f71c6a91c2edfa5b6bffc5b140b031957b7bb26055f1cb2a79b89df8b1c31d9a54d96d546fa1f77e3678efcd9aa875627419d1dd38c1fe743785739c8bd0655b996f5bba23604983385ccb75640fb0c6b128c2e117e9a5fbb7b25ab1d9e7a2db644113b
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = e2c50870d442d577b5fcd43778e9ac0e13f62ae7d506325ffa38fc267d697da72dfb22eb03d4c4bab3a9d904817ce78056633f93138ce773257ed88c5aa16923f2010c39fa4f38b2d529a6b61c9ac058a8e55775ec7e94df885a31bb1c68e8285a602c2260bb18a54402a515f04c1fdd3003da5709e621ec4d546f7c6cc7e2ff
+S = 11875488140cf57011ffff2c42926d00a8f2cae3367360ab338c96aebdcf9cd95c091840c416039f58c8a5fc0cee32432a673714f67baa42d4ba6150054dc88644d5c133903fcf02ed83e196078041bc96f2ce785e0759f0a7ca80f41c2c2a97196d0e4763330b74355d8de3a102538e1b4174de2ae8ac71ac14f8e0a9d9d9a71a34b953c0977758c43fe96a3cbd9ba00b52a72fe464b485d306979685db3bfcdfbec66425dbd20fd59e0985458dd4afbed8dc4a0756f38c54624d86ea71e9b1
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414cb9ea455374c24f698ff1b23b65a9a0e1980c32fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 2a5853c37f9428e1879034feb2d07a5c454e9970f4c1ff43b21f5918c8614d4f24866c89f4da620d7478706b040e1d5f7ee028f7c610c0f8a31cf77fcda875e4477e69e3eed3c6fe53ccab1dc6402278b3c00eb632d45f56d988884fd42733f3384733199505ba7bcb92cc5d1eeff3708cf435f55d974325fd6bf3d10767f046
+S = 616e467f569c1af563d7775df9c11116856febba4a4b7f801945b702621bad8cd599fe43ba381e02a67714244c0961c9cc65b6f842c2391a439ffab1d262ab0896e200493526f9047e3bd77e1b88ec854f8075bb54d7ebaa1143b4adf05fcd1f7873e036f464e73b4761505f7e96d6e80553260a95449dabc1e45f6e5079ea6fbfb8281c693005d3214e175ed18a9f5e70d7a59e87381611aff9cc82964bc6e68735bc11277f5c2e00be2d089511b12a32bebcb96ed91f4e158989b3869eab4c
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 34d9afccc659c8f438830b2fbe8b6600dfabc007cb22e826ee7dcbe2c515eb0cf1d90ca08a4d30edb5d3c6f6792a1f19ce3421eef7fc3f7212f7a965ee8abff01ccdcc8b498ff11ecb9a5f667937c99bc0f51a50f3a7639ae3ac1774b0737a62de3d5755ab25f1cfa05e3d4767bd4ecfdc7711f4662b3ae688237ed9b3d703aa
+S = 238a420dff7b0b18fcb6684933c38a9401fb2a6f8fdbb42b786cf5acb08948a46e42197fa690a613c8c0ba530d57d4f3fcdb410edaadcf995377a4512d09e5dea6de8e8f553d7694705929b012e7de002c95cd670f47890fb2077ee5a4c819ba2438d0757d8dfd1d0a83e4203672c269ac7a0c1e9769cb86eb3c9f5d7cd81058bcce66f1e3e7f47e1e15f000a02a7c98794f383c9b8650cf512b3040d1b6ccd638f5c8aa891228ea870177add8a9e754fe1a5c97f01f945dacf851eb6eaa0219
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 95e2657996a4fa69f824ca49ab5a7e6ebaf498a0dc9eaa7f4981c51fcc0935f619ec6bf862683b0025cc48724839bc1e67aa3c686d321ba66185cdca83ba9f41984fa61b826ef56b136e13f1239dadf6e03d877866ccb887908917ef0d33f117b614fd291e3e91736b15150e650db9bdcdb56317f0f5ebe97c938bd691fc9140
+S = 5ae8f7c7b9f7002e048f47d7471f83265860a70e7da64a9ec5053f07e9d92f2af5d738c79bbc9924eae62eb723edca05a965f48946573323132b482c04810d521277676145e505b515cb4fbf2f783e3f71124300bcc96963536ce8ca83086a004e4963b8fa52c4101073d252bbc242fd6e0648b61edb394d84b01f1d7bb28f24b65e89f5acc881b6d30612105f143c0bb871193f70d4217a1e283285518cba57ee85a3bc77fc9f481ddcbd5a78144685de81a6828b0a253f17929ce14c4cdf12
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 24b78a630dd8cde2fa183956b3edff7e0ea5bdcdc0f1f51172a3bf5218b7bafd7e9048422385fbba4b9c4a4d50958953392b18f98d96dae66a54e81fd12987284465586d9365cfe0f35ce6e250541367e46f77550973582e4b85d1efc235c8389fbb21ac0480319b19e176df5c2f850338fa43abda8f582f40bfe18a92e26573
+S = 6fafddafe9df19c45011ae4914adda6bbdbb20b43106d6d81faf1121c6300f9f9f2f87991b27a79d7ab8df8466539d4974d5cd379413ff1f2ab1f826ef5a6b128966fba4000593ce924132c26e3cc2734c38536178d34d90bb141576b80fe2ef1c4be81fde648d1aa3a4f537bcf815edab3cd3b44f7db09e7d5f73a17a9af84500c87d33b9d1ec7854852400c389473c8a13f70bc37bac6f75ce407996a3fdb9489fbcfb860a8b4c7280d3795841cc325fa0c9ce025ecb3f0c2d6c18a44c8ed8
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041cdc59d2d30fcd76a4ee2fee88ea165458725b7796e06af5a9bd13f257
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 165c3a41385c453b38d0ce2eef3a1fd2863535b993080c84847b1d5641ea24890d9726a0ad44b37dcd0269d59f44b9e0c537ee5571566a95cb39332693adaf64070aac7307c1a37877353e09e5cc17e26b45c3d9d74c0f140a4b89799e844366cc5dd3a28cfa9e94fd1157b308fac23e4006be2d0d1282670a5c2735ab9567f7
+S = 00f76baa258f67d94294939b305b41eba86c36b5ec68a155281a692b0be33d01d0b4c2aee3bb503a4f26ec4688b459bdd550dfdd029bae58f744c14b2768d184f6cdb9bf1e6da750cf10883f14d49ee5d836ba34b84eee98e7feafab7ed239b4154666eb0ebf0f3be6f44926656a0b9c5f649fbe5638d563fccdeaca8665a6a7868061a7a544b69b92abae588c8461e01e47f2d83f00978a99caaa2b4478a72c83806d24ba5e41447ed7fb6f22b1750223a9b18c8a2a08f00eb58ee20559dec8
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = e2c50870d442d577b5fcd43778e9ac0e13f62ae7d506325ffa38fc267d697da72dfb22eb03d4c4bab3a9d904817ce78056633f93138ce773257ed88c5aa16923f2010c39fa4f38b2d529a6b61c9ac058a8e55775ec7e94df885a31bb1c68e8285a602c2260bb18a54402a515f04c1fdd3003da5709e621ec4d546f7c6cc7e2ff
+S = 6dfff6e5d6e75fa6b9f012a13c4e62a469d915c7382f20c8b961084ab41cfbc04dbb150d5f50c7c1cc75e6e891b0950a95df3171decab5cd48dd02a62b51f50358248b1c47f1cf7949d78bf236bcf1f6803e27e37725b60a37ede16f951587290f4eb5b4af07b7a6c06bd520adfd29e56ae61efc3ca7d436a8af7c2da47bf201ba602896bcebb44adcbb54083a26b91ef32657ee52b7c69a98f985dcb37328fd703c26303c4863ee3efda288bd9565258b93298dbce897003c760168cc17a734
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041caf4c1d01bf7efc97ce8b761e6fb40139563ffeb393b5ebec6f015885efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 2a5853c37f9428e1879034feb2d07a5c454e9970f4c1ff43b21f5918c8614d4f24866c89f4da620d7478706b040e1d5f7ee028f7c610c0f8a31cf77fcda875e4477e69e3eed3c6fe53ccab1dc6402278b3c00eb632d45f56d988884fd42733f3384733199505ba7bcb92cc5d1eeff3708cf435f55d974325fd6bf3d10767f046
+S = bd10583413878f8c71938b58927ef67e7e46a56f56756ccd099e3df80dc44126566525c666f009b0bcd35ab1ed54d55a34b5e7e0c1efc1b8a54199a5d4605fd464111a40ce3c93523f6ab771d8c8b03939daf3593a020284815357958c7b69e8500d360138ab64a94237faf280a33fb257f4191b5ef385a7b9ed40e6fe77b6e85e471c3c7fa922a2044600285e2c71f5b76edfb8ac76c5b9ee0fa1856c632c9c3531763cefd999fd2f497efc4520029c6c08a8b8b2ae0cee0bc81b222dcffff4
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = e1ba864ce9f41cf4ee2ddcbeb7a05afb1f48fb88610b5da39233f3fc6f1df00f593567b29e22b0eafa3d0d035e488de0ef5d318f52244e20274932b8d32d0ae183dc04246e40b0da5a94ac3f611a80c8f511c7b722e290ec139a03fed89c488a6698a4cbdfb7e56b141801994980fa5c384d042758aceaad5e0caef604d370b3
+S = 5596571f16dbd20f8c64ee7c1fe8750910bf640837c9de5c8cf02bf1b36a4ed8e41e95e10be3038334c7ed93b80ef660b1061d3595c647a603d203d2bd9a357236679944325572748f54fb84f382a7d369899a82fdc5da17cb5a24e2811ca881fc748a6ffc4a6610a6f3ca5db07241f7bdae1d6ecfd7eea37b276d8667a536cd45c8841c5197471ea8959c253eff1588cd99355beab1bfbbcdad5c19aa507be24e826479058197313a94902d36df02770cc67a1c3f7adc1d467640ade84237c0
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 3730776bea4bbd16ab03e8dfb6ec4b962cf4312ec6432cc1c466aad327adc9db20d16d00c8da8f201140d816fd516e3d0ed20e30fde95bd4af3b75996451cefc32403951b28944bff93ec88cc966be9a09a35432731241018d735560da8a54d951c404e60e1e85fb4843e1c783f4e4b806ad2ebd9086864f475771b2f11f0378
+S = a9a3fac88d8fa6478302de5589304fcd201792e51e7f5e2f10305311fe804dc70728623b20dcccbc996bbc7dfc2ef283521480910df1bbdf72a51151353a791319181e586868f37f17499dc31684ea8632595ecccb553f9bbd499ad291dbbac1813de8fa06a53021bb674b198c79f5c8f2f28c84c09863951501a52bc7d8076e02adb656cafb940587beb815397a9bedd3129c2beb5cef8e3771e985b4a81be0cf6d50b53af7723a0ac0973fc053004831cc3954b2356e4aaff9aafd13ead212
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = a9ba6a22549b61aca519cfec89c316889f0404eb354b5f8d7268c174d43aa6fbde87c4d20a2b9b4605754cc21bceae96f09b9ff8726598480b3785991b48d36ca5dacabe49621d4672e9bff8d0b2f9cd091dbac6abcb2e2f660391217855464a687d23f0f78a1034543fd0948fb91eb45052fc5ec9c648c7e9949014d2a7271c
+S = c71119e288acfcaeca10f632f20ca3d9aab35d62f4d8ea66acb955d83c0bf0b9eeac6bb3f776efcb4bae51e47c3cd29ec5d9c8f25bb6f52956ba4ceca9e189a5dd24f1a5f314cc65c2d77b9c1450931765bca3ba701434cc9ce3c4dca806f1f1b7e11da83ce253a1c68bd306770f3d3e8be5ad242b480fab2ba73c20d3922ecfd5d3e4c66ab7a220ce1e175d19740caafc76005056a67326be67f413233810c8fabeefd00b3a3ec19178f48178c8df23a0d08e38179447e3c1f7ead1ac186298
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420669cf26386b9f299c4b53a9cc5bc93fde922383716b1bad573ef605208ad4741
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = c68bfecaa74019105206ace85d710f160907bdffbce96268b2b63680efac8a217810a053c2d0c0126b6888512802843effe1ffc8b6ff185e8bf518fa251c025fcbf26c9fd4bf8edf5e78995e43e34ab449fcbe58999888657348019e1f80dfaf27f809b6c353aa0195ff8419965c88005120a3b84ffada04d2759973c6204899
+S = b7873d5e394de2c8d17f988135da4563f12d449858e5b26e630596c325046e30f0a66ff38b97e8bd3c7b8cfeed4021ed08b025d7c8919c9c7eb29c980290faa100d4b56c1837bea27dfb862cfb216a0965a1c6a923a65e654569164ac93a3b39bc7f533a4b64e4e8a3b88d0fad6eda12e11b181c9abca3b776fc409a8f069ad40478c3f2f02b0634d5d095316813415ceaaf8ff069d85649b8f4b6ce82ba55a2a3b0e53274f10a8cc0c7863032a38ac5bbefdc735523a683bf92196be7120845
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 17c6696009d0ea40825e93872261234db051c06cb17230e339574b7802a4b0a2bb18b8a5a2caa8ff55b22b03e56cffc42d39ee346247008deb32eff072cadb4c3b173f82b49a24c74ed694498c0f52155952c8389fb5412415e0585659ccb0363ecbe63f67c9c45f15d1b8a13dd38409dea436bf91465b71626a70f2de339927
+S = 181e3c1d3f6f6ceb7465b6d232f0fbe3270bdd3e6fe05a8dbc3ca9611280b141c11b903c8c34e7a09b1124874d2ac93af9b3d8ff495d7eaf763edf281235066ac6c7c1dcc257049c732ab2288b918f1b7c43bc36f40f5fd070d362322109b51b85574b30987bbd2d460a53ddd694a972fea606ba2b3a4192dcb30490370454e147013d6c7ec15ddc72d81dd7d0601c49a00e61b57ce3cce8ce89b8048359a450a42ed1d7a424e725d75ed0ba5818b377ef809b3c32564562315f21c8d031ec0b
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004201b3650ae9361fac5158b27993f4f51b62133f7172673d0cdedc1820e3d127314efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 063c070dbba386b97c50ea8c475cb9817fb00be490184906d19a3535ae052aeb06cca546d21505b8080e8f00bf80b55993a698f14b3fcb9cb9e25acae2920bb75f92e3e1037aecbfbe8b36b0c1401c32e325c85444ecfa6e30be040f46cf1a37d935c8c696fac4356770e68498c4757339d6a4f5c3485ce2fed63cec21e5dfd4
+S = 97c48f987ae22938db183cd761956e3dde0cad8a865b70f2392b77f876c63520a12d3bd80850fa6cc20e9bf94d058f2d0a7ebc83186d0defb0ae256237a9fae92b2653284086d49b04ed9ffc3e10f6bb3f9de76396cb4fad3fcbda87bbb1df8c26e2d70f3d5dd0ae4c159ef3aca0fea506887666cd923435b0d40ae434a816b71d72b91a92b107721761adbc7b678d89ae5c8ecb0ab9078f8805dfa033e00a25b30c3c1c4ca8bb3bbdc36b7846267c2a8e5c6ccd97a454fe813c93f50eecabf8
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = e1ba864ce9f41cf4ee2ddcbeb7a05afb1f48fb88610b5da39233f3fc6f1df00f593567b29e22b0eafa3d0d035e488de0ef5d318f52244e20274932b8d32d0ae183dc04246e40b0da5a94ac3f611a80c8f511c7b722e290ec139a03fed89c488a6698a4cbdfb7e56b141801994980fa5c384d042758aceaad5e0caef604d370b3
+S = 1f01900a2786e048f388a061f173adf5247b68076effd95b5c174661b6fc3589981bbc03cbe75534af40ffe0e60c741745cd143f23c2d073e70856ea88442e56f6ebc26e8609b72a955f9377eae375913c032819afcf60cae66d893525ce0bb83e0184ff7dd85893443e10d7be59466c6b7276452501e105bd3e0a8f7553c58ed8700d8e43aad9efd827fafc1948288c12e380b82a9ba22340919a52a9453f2b14e6b7795215720cb6c2a89fa8bbeb46a416267f3126456cb6fdc9fad183059b
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 3730776bea4bbd16ab03e8dfb6ec4b962cf4312ec6432cc1c466aad327adc9db20d16d00c8da8f201140d816fd516e3d0ed20e30fde95bd4af3b75996451cefc32403951b28944bff93ec88cc966be9a09a35432731241018d735560da8a54d951c404e60e1e85fb4843e1c783f4e4b806ad2ebd9086864f475771b2f11f0378
+S = c5670f7a66b167b3369df23e847a68022be3f2acf2c54b1f9c8b4559466587e80f73b6b668921af9902b72a2cbcec0f92771cfdef7bcb12d3db6032b434b8aa2e2bb2a29f16756916887a79e78552254b702cf2a14c9b9c6c7dcb84745fe27c90f0eb7760aa4f98ed241bbe65a8597aa6d26fad59874b38fb48c2a69e4a77d7414b66552dc7a9b15646acbaac71aeb4c4fe69be40137e79a05ba512d40f86af2d7ad5a1893fb589ec9aa25854083f8535da0acccd0c497dd8ae3a16d3a8b3973
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = a9ba6a22549b61aca519cfec89c316889f0404eb354b5f8d7268c174d43aa6fbde87c4d20a2b9b4605754cc21bceae96f09b9ff8726598480b3785991b48d36ca5dacabe49621d4672e9bff8d0b2f9cd091dbac6abcb2e2f660391217855464a687d23f0f78a1034543fd0948fb91eb45052fc5ec9c648c7e9949014d2a7271c
+S = 29bef7b04835e0020a2cba2b9f6db73583493c3702678cc624ee60dca13ef99f58bd2466b3cc3515e3ac52cc01e53aa0b1ca13871ae90317ed90d5dc810a49b0f569cdf78cd4ac2b554f272f3aa541875478901c26d82835bf482451812460da6392f801293ce370b1dc1ca420cde9af65f191dbbb57e0868971451be9030f414c24cada0d759767b93526e39cee99933f4eccee7eabf0353fef6061ee271558144cbc8c4aaf2d2b6e9bc9dcf2fe3f1902f1ef1cbd4617b04281ffae8925fa09
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430ec65d014978f49b770a449d588ef99f8c92263e18690c237b1c0edaa8da55716adc29d56621402e375c606e7399c9a83
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = c68bfecaa74019105206ace85d710f160907bdffbce96268b2b63680efac8a217810a053c2d0c0126b6888512802843effe1ffc8b6ff185e8bf518fa251c025fcbf26c9fd4bf8edf5e78995e43e34ab449fcbe58999888657348019e1f80dfaf27f809b6c353aa0195ff8419965c88005120a3b84ffada04d2759973c6204899
+S = 80fe5722ecf6c505989f017b63fa71b2723acd378ef8c4b4de5aa611d99196584eed2b46160f4739906533fe54034db7264a19366f7719ef576d3765907f49792fdccde4b94db4b42c95a9c54b2fa67f513039329f3b3fccba4d44f69ed2c9cf3b0469556ef88d90391af612a273ada316756c36d447b4c1b36edf516e8fd0569cdc4fe2254d3165a9250a9163c9b0c629bc64fc7cf9bf96c3b51d78e378678f2309658bbb363ff462f51d145b82fcef1a0282278453b48cd8715d32dd8a2214
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 17c6696009d0ea40825e93872261234db051c06cb17230e339574b7802a4b0a2bb18b8a5a2caa8ff55b22b03e56cffc42d39ee346247008deb32eff072cadb4c3b173f82b49a24c74ed694498c0f52155952c8389fb5412415e0585659ccb0363ecbe63f67c9c45f15d1b8a13dd38409dea436bf91465b71626a70f2de339927
+S = 82af137868d165dd09c47c95c960e636513305030879d7c4e1f0b58c65fcbc10842f7794e0b80b019b4b384b3473fb452b9e04380f84232e986dddb79957845c0f69f880a51a73cd4bdd041d98576be7220992982ffbe30fe53adfd524dc5da9d8d21a2140056faef2e059a1b282914db1b83494026696601026ac038bed35ac5bc7fa317cf2302f4f211dd8bfcfa3866d8fadb498709bba9aa823c617f8c339d17d0094f31b945c1c8138c944e6ac6a601a705e47b25e9e290faa0550549989
+SaltVal = 00
+EM with hash moved = 0001ff003041300d0609608648016503040202050004305b2dc15a4a45f199a414077ae9da96fc71a00f9ecdb0c40e214da9b370763b672571e471a8d0328d5ac83d2ea45ad2a7efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 063c070dbba386b97c50ea8c475cb9817fb00be490184906d19a3535ae052aeb06cca546d21505b8080e8f00bf80b55993a698f14b3fcb9cb9e25acae2920bb75f92e3e1037aecbfbe8b36b0c1401c32e325c85444ecfa6e30be040f46cf1a37d935c8c696fac4356770e68498c4757339d6a4f5c3485ce2fed63cec21e5dfd4
+S = d216d9776d8ce35cbfa62808888f67d9a154c87184be9000322148237b8bb64bb75aa5a1773ca9d5b375ae4f643846d07dbc3cfc8246d8ff2f774ff42b184df3495cbadb81a8fad00c00f61fb59602c087d570db0ee1312a2747be0fcd9d563aa1cf14522ace1e202c76ce7849b818b04e4bf489fd723c977f1a2594d65d8595917ad0b575cea228d95d6e3a9ba6f6ca604b8650d5d4e7c182a487a20af05c15139bd46b2f2e48e5db0f184bfad5119a9c256ab601820b7671b6cc48394de6f6
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = e1ba864ce9f41cf4ee2ddcbeb7a05afb1f48fb88610b5da39233f3fc6f1df00f593567b29e22b0eafa3d0d035e488de0ef5d318f52244e20274932b8d32d0ae183dc04246e40b0da5a94ac3f611a80c8f511c7b722e290ec139a03fed89c488a6698a4cbdfb7e56b141801994980fa5c384d042758aceaad5e0caef604d370b3
+S = b4be3c1b7b85f8eff79c890661621f6f3e997ec0b957d540e12b51461fd711b1f7ef026e7f4ecd1298b2f179fd90a55cdaa8c67eeb592dc077d8157b8a04611c904808a6e8a88e83d0965b6f8673253ffaedb437e01e771fa652cbccc976bac41d5be23c5a11bc4027f38d7442e999dc4ecd4af036c201332f7bb1177ca523becf8bc98575d2c4cc4f69bfd9383e540a8eb70dae384f3f07e190f72b856139d5232c3b9037b7e05dbe596af51751da4fa33a03c1d3e847e5339f2fdbf4601272
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 3730776bea4bbd16ab03e8dfb6ec4b962cf4312ec6432cc1c466aad327adc9db20d16d00c8da8f201140d816fd516e3d0ed20e30fde95bd4af3b75996451cefc32403951b28944bff93ec88cc966be9a09a35432731241018d735560da8a54d951c404e60e1e85fb4843e1c783f4e4b806ad2ebd9086864f475771b2f11f0378
+S = 204d6b33a90f2ce261f413b54563f97b04021d081789d8b20bae89ce2ea0de539a264a7aa47e4e4cfb9864fa271f097fe1ef632363e3ad3996e7d7d4412138419d5e17c245ded83329bf6805880397b5d9c724e4185b86fe55c88b4e8f01056747ce712b10eeed8081b928c805c4b89b6955219d9441289fd800588012b4a19a415f96096144d88c9a9de4ecaa817e36e6aa1123bcceeeaa6c779fb7fb67a61773fd1c8e9dda482be5882b4f81217bf9019753919c0c98f3d56bd60ab4e8ad9d
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = a9ba6a22549b61aca519cfec89c316889f0404eb354b5f8d7268c174d43aa6fbde87c4d20a2b9b4605754cc21bceae96f09b9ff8726598480b3785991b48d36ca5dacabe49621d4672e9bff8d0b2f9cd091dbac6abcb2e2f660391217855464a687d23f0f78a1034543fd0948fb91eb45052fc5ec9c648c7e9949014d2a7271c
+S = 380e96b29f08c307d6894255bf104751d5c12892caec1f449311dea1eba85d63829c4f6f8e4c48bae11e6ce246635ffabe1f921de533867a738de08974c2685e7cb981c94ba95d50f2c663a90c281cf676655d542c5fb91818fa83b273cb7f55d88555068e9827de54abeeb597a7f66b20bcf542d9423826363716ad63fe29ef6a093f723d3a0f8926b678402fed69645b0fdebd943546fb0e0316e925eda23c755a321e23df6910e7b6c908b35dcd0b2e0e4c9dbaf51d050ad6d9d16f67891c
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d06096086480165030402030500044068a22ec35ac1e035665d558ea68f2d2867cae3935aede53c6940477d181f9630c3c8d24a06be07e006049c545aaa830a3ab849ff91d935df4edcf4e46868abc4
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = c68bfecaa74019105206ace85d710f160907bdffbce96268b2b63680efac8a217810a053c2d0c0126b6888512802843effe1ffc8b6ff185e8bf518fa251c025fcbf26c9fd4bf8edf5e78995e43e34ab449fcbe58999888657348019e1f80dfaf27f809b6c353aa0195ff8419965c88005120a3b84ffada04d2759973c6204899
+S = 7264f99a15645f551eb08662418097e48da66f7c3d5a953d7296330bfa24d02f87f554e19c20f98a848daa9de39a22b848f514826acfaebdd93db456394713547ca172439f18473f36243eb0ce85cb7357d04f011e34c139d72fc540afe0e7a5927c8466bf28a76e572c851493f23569ccb73132a650ba5af14ff2cdb20a3dca7fcc465e6ac6998fdb2df6f3d88044b4354cec5f7f6ce7f02d3dad61e764058f9a69a6c4e63d4e0ac89567fe23cd1eaa5726d567d7a647fc2ff4ab299a05a896
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 17c6696009d0ea40825e93872261234db051c06cb17230e339574b7802a4b0a2bb18b8a5a2caa8ff55b22b03e56cffc42d39ee346247008deb32eff072cadb4c3b173f82b49a24c74ed694498c0f52155952c8389fb5412415e0585659ccb0363ecbe63f67c9c45f15d1b8a13dd38409dea436bf91465b71626a70f2de339927
+S = 5d90ac2736979a5a789b927b6b142bf08cdf50a5018e9e75cb03363f255d4bf10e0873e39c7cfe7f0faaa2594b856ebaea0b3a83c6c1fbbd1201e533b2ce14e726ba43aff51445e976f9158d6b369fd121e17e34e529a9f7935f3583943fb82eb0e551e7a183254cd1d442ec87d3b853613ced92c28ad87c7884b8e57729fa36b25767be0b77108d2f1da7122c3c44f71ef1fae6399400190863764d2d28076953e579bd5380058cbc06671b76d6cc2bed1bfb1eb0a22e72308c5c294bc4d339
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffff003051300d0609608648016503040203050004409e1ae481b6e7360c34c33703717c48bf5c84b980c112931713bb8563dbbc3542dbc309570342b078e7955ded523fc9b8e992724b26452984214d8f3d04a7f0efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 0b86f0524108c0868477219f6462fffcec9e0c3f0bc83ef154f23be0c51ce72969d5e94fe758df4988bdc97b15a26ecd30b1d985794db76c6a9457cf23d021b84145eb1e94026027f6184a83268334b36c5b1a87b054cc6ea0152c81c8b2221d5994cee154433655352cbbea66651f6e0297fa432f66780fad7d1797d5d2f59cffed6125810a6db340502922acfd7d0c0103846e5041c43efc3551adfe7f08180611bcf21175160441b81bc2cc8d8e922f8e21db688e25a820453ca986bc4941
+Msg = 03403f0e704c5e28fc547e60cdba09c7bdb7e4fff89fa2a0c667f8d9a564715b9b556372caa4227545e9736122b044c1d17c9ad1ac0ccae2cedcec0029ef8dd3d3cca4c3a1c7c75ff7819f00deb29aa95726df32f00687a694590ae9a7caf79e53ace9471c3bb6aebb25e98529497349fabe9d6cec1741b2c0e53adc487e1984
+S = 5959dba95cc8fe826428883acbc57294a10e8e8ffda441b07f8fb2ad17f52589774c27c2f1cb54e96614bf7b7a89c4227168ccbea47a941540d2d71157844ae0210c6fb7abdb58db349ce1515b63303f85a6bdb38bd6ea0f9a340fe70d3aba17f4b5f2a36dcb37f354eb86533e4424c7ccd8377775a28f9beb6921c8b4d9e89811ff748bc1b026e9214c9c16227a36f803cabbd738025bd9f7cfa1c33ed4c00b5d8035389c8d6a02051576d33c8e83f2f72fdc1b35a0dde73fea1e2a93dae015
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+[mod = 2048]
+
+n = a911245a2cfb33d8ee375df9439f74e669c03a8d9acad25bd27acf3cd8bea7eb9dbe470155c7c72782c94861f7b573cd325639fb070e9ba6e621991aefa45106182e4d264be7068035595d7549052989b3e7fd04cabc94012c1278a0ef8672b1a51dd1a9e276816ba497dea24b4febe3dd8e977707bcd230ca6fb6f8a8bff9e6ba24fbadcd93f00126b19b396a38e6ef86d18fef945b9154c1963fb488c7025953511f86d05638bfe056493730bc6778446e59cd3c5c3acf07a0a3a64943793652f10e3292aa7a6d25a03181cc6f6ba0658d909e59ce2a02bacc9766fd8c4fbd4ed9c23a866844b8a794d49e505f9f944870a71aadbe5338039825c2dff81af3
+
+p = bf96de108963b5113399b664765efe046e2dafdb70d6e5e29dc6ec89b789b059348d74d89129c7ade9ddb404c6dc3a3437c7fc9f23bc38dadc8ffd0ff757999f5c2d510b993056147ccdf421e03d0be2c74ec333a9677c430cc604f5550d0d86defdde71488e3db889c699a5cacb44dcdae2f3cca38695e783e6f6250827efb1
+q = e1e7e33618d1b64d6862c132e4b1cd5fabad20ce62bd97bce2a3f5ad2da67bb0a7f0b9e48335a33b7b95e77ec4c47e91416881f9f7c23f9bc1918cc644335c74260e90cd7b2e0fed802f19e78c5ed80a431b38630d82f982c74a0381b8ecf943c60810fae90574e216357b2535002316d9529cb56420f3cc82dea37cb624e1e3
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 04d5d202ade6be1df96d263021141bd6e4e68a14c5b413df73b817df8979137377ee2df5c0e60d3f67a8ee6ea3d6f5e6da97c196cdf4437d1183d06cbe43740e6bc88a2759988919eed421ac651b870ec5ab0d190fc9f5d5bc64873e66f56147c6a90f1edec2dbb2773ae673ceaa78588b6b9527f2fbd1f15da265dbea558125
+S = 6b2703ff1a8d96808bf97eb6d297a8b8d11f479e22b8471e03d2713d124f7c8bf46225e8de2b9db432c39209c242420bc9a17196a38c1b2daa096a73e33912b353a6adf9d198d15eadb6f287c5d2379fe8c07d9e5735bc4c474c2ff9bc7ee6d3684335f7f825664d6272426b2fa20bae585f7bb306b352d916679c68c77ce0d2032cee4909fd02f4f4711ff4e771251c3a9e284f37fb1bd417d8842d030500d84bf7a774b5bbf089e2829c7e7dc27f4d88408e5b549522339e6eb98d51718a219c0fdc20e26bb32d85ef877a5fae812ece7bb04a1ac5a0dd71ae4e8d4c25aaccf8c1f5b9c0de7e0491cd754a675ab6eb8c630b8afc49e0597ea6cacc6c37fe9f
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a050004143d68a61abc2403258d48c94be567caa29e315c8befefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 3efa6c9938d6bc37f0373d0baba3697acc3bed498f9dfea7fa0af06e11c405a64aba834b4067094fabf822e390ad1bf3b58112ef580d50d120aad95c54d640a14bd9c0c824a8890db7095809caf84a338949f2a63090a9250b3e255ca00c4e682b9d4c9a4a5ee578fab20605c24c9f432edbb4f57fedb2a9a10dfff65d2fd403
+S = 343014b8db6ba664af3dc07530e444976bac0a7fd3505218500b0342c0c861d508f55383c18ee70cf47516acabd50dbc2ec18a8cc2054ab87496b9cf22e4f576d5f208d0cd3be114f65f69e0ae744e46edbe0a378942e24eb51fbe25a0caeb654b20ce9a8feda1bd02981a24ed35fd139d107611cbdecc7b1a960ec57a19eef79bac1ed277b746772b405c7c29cf8e32c1c7a49557928ec792944bbc87183fe828a3469214fd35c8ca16df57a985d610ef80db9728f3d31529a7c39da03d39a6735117dc99225921d26fcee7779d7ae191934452207bddaa60c0aadef72c1ea09d5a1d7cac615a8a5b08c5e429d801f868683a72263d80db270a413a8fd9c4d8
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 0017191f1c6b5bdf895837a17e05ca6119ea3606aedb978c5f423962ecac0811cc87471f7c2985331715cd79277a1e48bafd1a03b9b8023d7683e2208472090fcb9fbc8adb292c52817ca5ce98d307ae22fc7ace985b5e5d7e32813e392095ae25e7e128e3723685f01625687c186fd9796fbd30f2cc91359ed87d85b5bc9338
+S = 1d2db922b68b7e89cdef4a238e033500962d61cd39bcad53494663921ae6b0f7710728d9dfb8d52d7725d4f11ca058b1195b1c3c4614c32dce6a2b1b9ad1db261bfde9cc8258787fa7ac9884ffb5e69775ee76ae8af3a15254898e8497b77d7cdb161415a1615eec8ae7ba4ffb352ba459a1d84e43a04b616a13cac644b38c528047841e249ff2795ef2fd066615828545d04c82e92a027bc110c5de6a52355e02bd7888c97dfd48a925528e48890323c6a4f44e5d04ea05cf3009e838a6bf438fad103ea8ffe8d0f7d770c0034de693c7bbad16e8c6a923cc8976bda5bc08b15897075162068b39b362699149e0cd4eda9ff1bade4fb540dc27c17e4119708a
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 1577757d0f460af152dc68b6ab25deadfebba5f68351bb6e2e51ee766fc437f71c734aa3ac4b6b7da506839b5708732acb87a8b4f7eff09e33858cf5f14a866aa822459a11355e939696ad940823a51590ace407e8570a5dca42cccba96b44cea0cd8beca8cc8a3d0dd30d2a233c19753570807abe4fb2b4dbd2d68201ee1a2b
+S = 5322e332949c0f15fe63f09927e2ef90a0f1eb2262fc8a7dc602facf8b5cf74dd0eaa2638a6d4393c0167be176e8e68d3b1a6dd4c7f043dc81e702b3b2620df5a4032e6319ff88e19c9cf57fc03f3ec5ca75db70b6b22a38f40a3dc214b477da2e1400eba49c35323c8d83e5159eb4ca6701b4fdb99f18505f266ccdcedbeae59b36fec2616b04da979376403a435d3aae0113d4605b9ffda0afe72923ed2644069a408c148b4e781387fe49f3103841eff840f0b39b298ab4893ba2c292af33b57f6f6f69cf5464be470f678ec07f0ae97c9ff292d896a7daec48cf9e48ecd006acbc2c8567368be62f2178d469ae958ac0b5bd66917944c4b53d1f42ea2f20
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = b72914feec0e16233c24031390fe31942537dfc03d58810915fb597b163147414f22e26b23f3c7ee3fed32ecd0dbcb36f2b3c2106b791d3499615119a93410740af4630021c3f87a3f01bdf0d0b5ae3cd52eeacc94ea0da48db6baa5b117770fcfe9be454f4650d022a9cda7f95382adb5ee827c1f71f861da43bba796a32319
+S = 2c2a5042129ef97c6235195df1da7b3d80e08176900daa562ea660258269e1a55c73bf226fb54d21f28b8cc02aab8f453405f2c0ee6682ec8ff2d1d8540aec1ed953f53847bc43f0c89608164532da10188400e9e7850114ece817aa854024e696fed5ff74a3747de548fe431d4a95c789bb377a8add64a8583dc7fb203fd66ec9e476232c25b9d454aa9ea7332672cde4ef7540b12ee28524b6c399be32805ac0f7f0db08eb07b93cd24a23baabccdbf5c8437fe2c3330586757a897242c8f2673ab8295ee88e5ec2222fd6519fc49cb1eea3d21d63f07d32bf0874dfdd5e74f511b2e06750ceafaef4238824f92c5da128042dbf64557cd6e4d7ee35d479b3
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 25d08c937abe386aa08b54cb9d7537829c478e53e67df73b0da9cbf76a153acbcaaa9e7c6510099e10172016b3562dd7fc126fef5561b5c7148e2ba6f2c07378bfd7f7ce54977e25c808fe6be71cb1bfdf936b793d1c2b6a18bdf0658c74cefd6b1f40912e99c086322695d42111edc4ad932bf885f782ab81fcc33a207b73e3
+S = 93a032b6e997c0f9ed6261cc4617d98afb80cbd6450a3d9ea2f63999dd68194c9451538975d7626d77a34734d99b5992f98ed18c7f9dc0026fe34cf6583a6a36eb6baadb8316e3aa48d9da4244544da430cb8a19953d84ad4575733d887ed3bbcb4f25389cd36b1c565bf661b1c918a14e5e00e0f0857900ed4c98beab9fe6d1f66a0df588b61afae9fa31e94464d85bc743193303259e9806231cf5cdd4d4c9da5691c08156aa72f4da7607d598d450a5c852a8b3f577194afece74e59fd4ba8c5bfa583c2fa9a6f6aca7c51f772d02fe8e0bcaf5e4c2c7cdd6a38f7264d717aa2b30daa6968a4e7e7e2dcc1de9e34604f0b80c8b793f882d35497d81ade352
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a0500041461ba8219a8f4252ba5e715540544ffde89da3072
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 04b9dc9e05391605d1101e84d4cbe1a08bc3e12a97e7e21e10bbe6cb1ba15c34bf5895b7f4c277ecfdea75d0f845bf23b438b50ec2dba209cffda7fc3168f5a4bf653f39e683704ef99599f8c9fa2d3276217080844b2dd33193a7ad062cd385adebc46d020567f26c1970446e7194977985f9c805c0eb44e087d026c5785e9f
+S = 39b142d1b8340384b8eea14f948125101c3c54bb339fc06a5dfb652ff28df204b05561e7ff8e1e6630d7ee9dc7a6147f6f24ddd703bc753cd3226e35812a821e68b7a77cae8429202a74dd1361e8e568f99ee2799a92500a21c73f98024d091c5e29e9531bfde05a7959a3d8f390eb17a6292d11d361a0caa7a5cd2900df5fd2f09679c9a1e58e525721fd068061e5bf5c95d1f491da063532ef620d537a45dc74cbf249c97493bc8985cd0fafdba295fcb65b5ce134cb30d504c93a999909e0cee5aba1d6a6e1f3a3d25403d09bff303d6b89f6a81d8c570c735ffac0d0d415c7b6cb7a10f68d94cca2f1de7975a5073411529b48b2a148a9353c536369df48
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c330514ff465a496206061832aa09d4d549aec683133b10ea884bf3f9
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = ad12e61576bc1b15d5bff13ab66a496bb5f643dc8461bc858d7a15d3d938369d314fd3598305ee9087429e8fa1e70e600a61c8f82b7e34b2497f5bfc676ef15068b2936775e04da99ed45fe7c401414cb605e4919a803b718f27fa5d90149e709b60ada513f43f48649cbdaae55ee91902091e0f9a10d9aaa699795c1cd243e4
+S = 3009202b1060f77de9e25bc5bf80062a16fd8c8a7e27c4f8fa2d069c6b706bb981f0e2561d8dafd42c647c844ff30b0a226704bb85a3a58dbd5baaa8e19ebfb7635d4f502677b6575b31ca37ba4a51e747fd97ed2a1fc330f2ddfd10669aa9ea4f13c990b4cfa7e15e983459df317ff83506803db89d9f15f3b93ca0acb22d800d9a2c36770718b62a78998fd13471107afb36b700aedde93fb9019ae9aaa9ae4f33d7a18cbbd8474ffcd38a6b4dd95de015786e50811bf3de5dc7de6c3eeb721e8197a8cc537e1d076a887634cb7af055305218680b605055d7e999b90a348745d277bc36dfb38c431c9edb329d3c5c750afcca77ccf159276ff70b6e8f949a
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 3ede763590291420c8da355f5e5930447317445e61d0cee6970dbf59a4ec4e679123ea0c744373fd423aa945e51ce5308e2307684df4af5edf23b0ebc7fac138a07676dbb1936f42c2c9d0552ed7f0573abf560da512e123806d46cb4044c0a712de02e96ea171b9ef9090d76212bb811df5199792b2ccfd23f36a413852b17d
+S = a3dfa3b5ce640d92f95260d559bb5c40710a2d3cb38b816fd3b790c78ede96bdc213e7e6e76f35d5e24cf1a6dc54d856be83e352f55b3caf98b6dffcc952023978a5a6900cc9b0201b99c90795c38ecf0a3dd5cfd9579378c57c0083b2584a3bf859c69a553ce7cf8c1ecb98376b4ce90e1a0271c4043654f175e90477440f7108b960d1e3e2d00743e0a2db96d179999709722b046070c4ecb6f3f3650365119004b016e62272fe9e7c06999c8b1f8e0ac56f46c668103cd23f1457f37e376b8aa5c4235db08ceb577945f3276b931f5933bda713f0c8643aac2b0ad92f7c8021da0072444ebffe55d0cf183f002ffe1e8c221508e7f65b73c05f9362214440
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c6622f8e46c8c838679d4e8af043ccdd2f9bf3a6820a5dc64a446fe67efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 250f95cfabab5de46ab2bda3cdeb3228cf7330aa1b5764ad75623c795634a9cad69424c9cf08ef3b40a29df9ef1cd4a053285289b0012efc844660a0220884369d22db87e7c8939b3a63482cb79cca5a4eb721a1dd23ce079c4f549ab8bff7193e5ec4f23b16d16c229ec6266d939cc087cba5d8eae6cd3884251f4d60808bdc
+S = 580511902d07b267c4daa41b6660db0d20795afe0320a961a36b384fe3537f7a88e31e09c5e3f660d2ec4e176c2ebf7e45be1b579831c0c75509380684e5936b79097d6c3b7262583e4c2f81ba09e78e542e823e855ee97260e8fc9d53fac6d452d601d07526583d078e293c0f183d716a0f7b37de31b000ca7bb095303d4eca67393886e43ac271c119244d4c45d98212924402b37660c0f7dfcd34e4672011d1aa721337b1025bdfbce502f017a573a18850cbbe108bc9fa978078906a4c1d4023f8158cb5224b46f43f70c8029793981011d77c816749f6ca9a71c2749e0e151fc69c7f4b39fad8e96cf4dc6ae451bfb506d9faef8b377b7c5b47e19a3a59
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 8db3a4d5a7b2fa1c3cf85a9e07df0aa00eeacfe1defc527218c7c8c82c86d21065efa2c2266360797369cc02b25a24b2b35e48fdef961c450d9b2ef0ab2899bd5a132958ea82bf2ce95bf77866fc09a5fa2dedd70a52c3c246e671bf75248e1e75077fbe7d75dfdca6b72529aa2d801feb400694b7970e90ca8eda5c14e47adb
+S = 9724b7c6909ae1499a06410557882d9fe49a804c68c172cd5945e40132d750d47a454f155c075c0e57003f20cef4a1edc84d427b6bd9f61617ab502ba6dc5c6b1d032a380898bacb80d5484d39783dbfac37c4f001fd8d4e1bb2310d459637be04cd5fb2cf6b32dbfd214b8f7cc0dada942cc41c9f476bf6ffa502bf7928dc8610ac0097dab03f79171046af23887c2d530463714bf7fe59933cad26266a117cd355d0402a4490472b0006f6e915c56e204eb480ab48fe9ef0dcde5660cb9ad235890713f77b5333c1314dcc741c2c8d0fed546d23696275a8d578a0d39d4f1dece330d73ff1c20c72ea82e4b714db309a0063edd35b22f12ea68f5c5723c8a2
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = d6fd570826eb30d7f3173089ffcdc2f791c60cb4bc5760e6e3e9d3557da92bc21681ff7a9646192bc6331ff5109673c487c957de276455b85db1de0eca603132447c7ea51d9e4be4a8611884fa153e81eeb81dd46c227643ea7f167d3202b56666d81db0425b8faba289625e44b4edd6ce7aa7be13f88d30923bc4cb3ff78006
+S = 4c142307690bf57792293509295ebe275716356260e0fee39e72b64fd6210f547bbc8eb84ee2fffe5bca0121735f934d1832079031d9813902269cb6a814a71a09012f08f6f8ae10907ca0755fae622328feedd8da1ca666d2b713ca0d5b6de85b9b1cbbd6874dd980f304a313ca07e6c70a44e9dda1bed3d9a2cce521473661f33b7fa96c496b8f7a9c77e9bd0ae0dd47bec92c2a4dc9f75af9280402a04014523957efa5f52985eff48e4f1bd54858a956743dd2badf858d00c83213908baf95c527afcf0e32f7c97d4dde5dbb936ffb09500a2bc0bf71839d55489a21d642ee455dfa8b525a4d4890b2283eb043b3bf77d2ed7e2885c32b004fbc89693380
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 8457c53956849cdb39bc8e7657d62a2cda9e13e1a5c3574142f1fd041c3add70efbab5207c7b78058196e9aae89b69bc3f330dc96804f44892d5d8da68f3e2cf87d3c3ec36f8006b51178d44877a9eabc6a2badaf2301110dd060fda74a9319136e91824ebc5dc179289a2cc9b3971025632419bac0f55a20dcacb8ca92372be
+S = a2a2c0264dbb8b8810aae0b9ec7408553803dd02be6247358ce39f98f0c0f0339915347ff3c4dfee0e0a49b675ba69e376f3dbba56aae846cf7f986a0a5f37fc9971a58e3217cca26dffee8655f3025bd61776683feecdde546fa88fb881d619a8ec2daf092079a850340f6af41b2dd11d9935bb06c2253bdbd32a6fb8bd5317d3c9c3be5b683e7fd6366e1816895664d8ee312eca47ecf862be009d9df699a7d2f515c69e3093fd50a3babe9ebaeab6267086a3185a908ea29af8eecf81e2be7c9c2ae33cb2380c73af264d24961b5c7711b0289e1a095f2966656ead1fed95b6c33d7082c3868f1f7b706f9442ddb76e3582f73e4839a0a110dbb78e9cfcc5
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 6918d6328ca0a8b64bbe81d91cdea519911b59fc2dbd53af76006fec4b18a320787135ce883b2b2edb26041bf86aa52c230b9620335b6e7f9ec08c7ed6b70823d819e9ab019e9929249f966fdb2069311a0ddc680ac468f514d4ed873b04a6beb0985b91a0cfd8ed51b09f9e6d06da739eaa939d5a00275901c4f8cf25076339
+S = 794d0a45bc9fc6febb586e319dfa6924c888594802b9deb9668963fdb309bf02817960a7457106fc474f91601436e8954cbb6815350b2c51b53c968d2c48cc1799550d5d03b41f6e5a8c3c264d2e2fe0b5b8ff53fdcb9dd111c985cb488d7086e6548b4077ec00721c9cb500fe07a031c2030e8ad1dd0112c34ffd9091d77a187aac8661b298eee39eb615f9715c4c48a6762ede55a466ec7f3cdb6a937cfc80188a85d8f8d3a2a80b199ce5e6375af8f02f06d706a34d9cf38318903965db54aaa7d3fa7a7ee58034cd58c8435739c8906366e2ddba293f2fb2c15f07fa4951014471e7f677d3bdacffc4c68a906e08d68b39f9010746cbacd22980cee73e8d
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 4ce993829f7b8112277cedbf8b4ec59244cd7ef79a7bad09cfdbd1109a1a7348d7f472e57cd69853cf4070c2d66e5ce20f37e2eb623547e154265f167d92a3f03caf84eca981ffe3cb45728d0c10ae43e9b44d09eee346cbe297bee73fb021ece5df72a10ec4df4a85539926137ce23c3a0b685826cdd150e1f4978bc6bc16c4
+S = 29865f133c69122e1b309b299270b5d693db89c5192eca5c829c795db460cb1dad3d1f27d200790fab035c90c00b238384bb30ee30752425f2b7f424d71bea79993046100760f3fa3c6e019d025338c13940a97778ea67e6d6138d8e8ff601d2309f02762add479d85d25fa31bd1c89af97927dac2ddf818cfe2179548db4da69c163d8cbf5f9c98ea33957022a52d6f33b19bbd3d05f40f2dfd49d999184cf5f9bc69fc1b21359c3c85ddebb6936c4f49015026539e8c4aad2dd3a3b4ba309021fb317348d12b560ec608b74f812e3b74e4c8407765f30d6d03a5c20db821adc4c844018d57fb5364d0e7c3d55816782200ddf92b13dc2e0d4665b4cf3e1059
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = c801a9270165955fa4d85fd502c0e6be0c91e1c453ef734f331300034a6f3e8a2f958f9361558e1a7e25e7eab6c76d617e256674898029f2f4c9ec0dc14fd716869b5d886698cb4841f8212b28d222b91490a731d70838cd52e9dd46e959329b34dcba0ff77875705517b59f402c2d4d34994b0325d1c865b6397db7abd578a0
+S = 290d0d444ee458777b5fdc3207d37054407c0dfa6806296869d3ec402a18209a3d06eb63d995293697e8c0a0e72489bfc9132857d6c7a17f4852e4e573a48d2a2a127fdd270092f5029d976b060a570c90d685bd2325d80c9867a3b245455545bfae8cf87cff314f4d0a968229446dbf24adcd2a52ef9abd30b4746c2e04c0fdf52655427eb03bf63fdb208c6a776a3852052ac225eb33d7246f7ba624723f9c22abaf6d2f9219181ca62e44bb53a9ce8b45e7c6d742586a234e5de66df4ffbf7bc9e7f815a7d5aadb2f727f3151afa6ff48f6090d9fe08c8b0f1505598ca4a4ccbde6ab0f87b43059065097c737e53dc17f200c3a54b00d709a5b8bdce80f2e
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420af8893e585e7d2dbf3b8d3dec0802db4ee1ae86e8bbe369d8e1eb3aa634eb2cfefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 2466a246feda6fa5cee22c2f33ed9d643c1f6824d9f327719225bc7678cfe4c85cd210ed4077701b0b5650418177a74c71b8eda3306e2ef3474f5d326990eadea84a9686e822878c932997298e01f2b16c42e019e21bdfb67b3df5478df444366c97df1bdd23dc82ce23abee44d3a61e9484e88ed642634197b52dbece451b59
+S = 79c3b93019bdb8a6d6a79e813e4d96928f730afc010657b1eb870f2891219de5fbd464fce97b2bda12a9d84a3d5c120c660ed0f70457e223809b26a996afab7c23143b411a1aae566d7e9d19d278044567b5064bc918bb101cadc7a521c31c5e1962a7437d8f799ee6a76fc2f0a6733cfcb63246b1a864bb14ae70daf848824da565892d750af7c5da6e02e4889143a746e7e58b562d19cd3cf3d97795e50e1dcfa26d43f00357c92f01b327718d6cd292498dd29d0d830408b568b2c91541a76b21b5d4efea46bc128d9c4aea4e9f60a4a601c876736bf9312a00a2bd81b4ca5d8e37ab2c79dacbe7d8e6abcc4691db64649cdff212f467a9d805b2c38cd031
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = ecb6731a006eb273f6c5404a2e2d1faa5232f7afdff5b69be1dc7927fe88af17b5077b11e84b5baf98db08d3f1c99d3b86e4fa55dd2e6b542e91858368cd51d975b5adcebf9bee6ef309caac05b276f874a70b14cfce2e237891f003a8d3f3dcb328cff98d45b3d78db5507c72cef20aa4e4f094bcbc47304543824ec480dd48
+S = 8831265bcd54bf33d8c46cbd48052e9357c31afee92276b1b744e2521da9b83968e9ca90446064d8f174b248f64e792f91f4fae15252688e0f8ad38b28a532ddc7dc59e77d81b7a51dda2df2f2cbd5195c87b66db297b74296d4058fd00a060377dc1ec286c21e4f84c17ef315d443e89912e6b5d5f7d4ade31cc2b1aaaebcf09aaca20041b5f9b799b5b532391f85fd236ff3fa794baf4b25a2a188b0746728f1cfe0816b37d8dd648c53d76b81ee42ce27bf07baa27016b82c9ef3e1f5523ded7d35622d4986a6699b261f483e9b68b9c99e17e4aeb1c7baa84be1177264894ed5aab8592dfaaa652898b37aec28c19d154df27956f604bb6a30d0964d4e97
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420e45bf84dc5abc5c28a27625b0c96d7399fa1bba8fdaf1d5b5354970b2ff9dec3
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = daf4399ffab3de496e3ec347b4ee6f4ebdbd83cf434ea81e5d2dc6d351577771a9fdbb458985ed913fd2f5ea1cc5c0df8203eddb3ff9c94d191e7e05aa7887e16f6267aa1b8c9b393143cdded1f34a02d2eab60a125eff7f0ab28f6ca6f5c60853aca79559d1d1886b1bb1ea7c80f7fed5f94624658530fd587061d0ebd51a2d
+S = 38aba878044ffa4572749376a12fa96b3b8cf778e68baa7ae05b4cf0457242f3a1eb8451678e79ad73741e169efbabdb0469a53dafb627ca3d14fbe392fe311e792b8f274e0d8439de0d9a82c14082abcc4253a5a7292f846ab816419b34c57587f2fda5c6be4f4a3c4130acef535dab4f0e05f5c8b18993f57b167298ba24b0d238964e0fa87114079fec872c673cb7d961ccf7ceff7fd5ada8a6f309de2d96a40224b12b921ad987b20e0ccafad43d0220e24b82aef90151befdbaaddfcb5b35e505912438668b4f61745734879c54c1105983c83a569560f35265be0d3ebcacedbce139c489f4be3c3befba6dbd6c5c92e0441a4a789ea383516be0f4540c
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 6cd8ccf65bb3833c81961801ec68a9735fefb8a5f7e3e63c0e47fd6b60f934216c87af801e444692aa9b8737bba4fe62cdf5b485d7bbf54a2e095684a66ff765facf06f16e6c84b2b2444cae0aa05196ace9274069bdc5579042895210ba7ca2dc58d8309452c70661386e4c21842a77c47219bdf512ddccfd9b9cbbe5024b41
+S = 12eede9247a5fd5579fd51f172ce798d20f8d932326f21ab0dc698711899c68357158ba1eebe07bfc1a78a08aad655da3a26556896267afdcd5e55d2ec91fdbf79960321ad13788e33eddd06b2f25347af73db9cdf628e8ac7a57b2a03555aacfd4af01afbd049dec0be8e279ad369a3c606fb1663e4b0f95be5416c5ecfeccf73c5d829ab5041e21ad0d1792b4536033f518b411c3c82ea162cef14dd704d23a278c0d71ddc9adc4014379c920e54ef8487ab3f5f6e991e50450c609fa769b60e057e6afb511df74ba7cc6458fe493a7a23e8267a742d20600f3c9261efd554b4c0b366ec0562c94c4180f34ba40780a24e8c36e110c40b6bb28b22394177a4
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 5fa43f0df5b0d9486b1e5f80a604230cb1159cddc9681462b47ca1aa547856c97bb7ba7c0183791014215a7fd00f71dd0f8996f28351162902b0a8a920b8a2c103cd6c89736435c63109e60f8aa7542e2b04bac9378b6642974eb2db924b361e9dee3c7c74d8743469dfea76fc5634c8ad8ef0aa0e9c6e751c5da989cfb87ca7
+S = 268bf5a0977722b24a174d83dc7dbec6ca1c392ad4a48d68af1b1ce30034e471dc8ccff5e5da865f677eb85c1e3022cadc89ec82624bc8ce5c632d1863a4946f364718f3566d38dda330ed68deb56130d10126fc9dc4f501f36e6e94507d5a556c8de76efd8149276eac52d16af495679cdd4361f66b7d963b9faa5ca0f8920227071c519f3f1ddcc7c03870a9639e78ce5f1e61b5291c190a4f9ef237116ebca742a513efe5fe39b1dd8914e71b60128b0e180685008ae206a64cc51c218f45db765c1af655457af34f94789ae5527dfa840a1cc9dbaef8003d81d3f59b7a3c440a9497da1be98182cbe368f0c984710f9ec986428f5c7a38313d43bcf680df
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 40bf49cb5825523aa5aea4c0e6b08b7f857f5e8a1ae01af731c14a364d272aa12d670b534d99f93eb04a9c78dd715cd628a4c8bc328c3933b397b23c77ec0b65a7a44f994a37623c0b34e7783d3660d11c13970056563efecaf0d25f8f2ac5e138dedb4556e7d55d3fd64d670ee6e199eb3393fd8d26707ffc3470459cc89e3e
+S = 825731d01b0c197e2b27c4314b256ea5bc09ce9f012ca120695ba38c0ebdfa8c8802ca5137ef675f76a17038780f94f753b1234d0531be8fbe82e557d9357b18bea2a5c1cb83dd129e31e9c2aba44640145d2ed36470ee57a9486fe04ae13d1be2ea4047ef405a53a2d4f5bbcd21c9598de98046191bb605ce7004e3250b128a0d7d075ea7bab16a30f165fda23318547481b8b6c9bea0843876934bf7c89e013c9f19a8e661ec2e78013b89aa6beed57d88cb27ac34cc18f231c6e6dfcb8cc1580fd5ea8185b927147b564d31f724466d64692a17dda68e0b8fbc1a7cfec4bfa9c9f96f73bde2d0ab8948d09e1e739d5277a4d3d4e70236e9a3dec388986684
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430e57e40b2774ca1517efc987400aad5a59ffe873f0532d8a092db7b4f7be006eb591eba4082d41eda449a261187bf3804efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 752fbf49ae63c7853b3ef6f52ed324e53867925bd5d4c49dc42b93f3ba9d7eae579c4169593da98f10e1a61e1214a2aa2fb511a4a75849dc9be89445c29184f85ddc877c6d1cbb45230a047a98ac5bfcbe7b69a397c454cba44fd90fa13f9b546f39ba0a52c8a8ae5c0038932962f8e3cd00c1e00be28c70c8a787d9be6f69c9
+S = 80d7286710e5f165eeb63d2936e8e313ac5999bd297d35590c2b6ffaa4b7b7ed30003f0b83c1d1996c8593a37bc5d7b501a3d126ac6124779a23718497002d9dd2ce891b83d185e333af05460c6deb65a509640f775a0d3c70e55112c2e4af19f4ccec7af9ebb34226164f1b47d50b8ecc1dc3e0fc09aa15abfce5aa3998b5c2b1fde261c35eb43220f0d64529f723801d7faff841faba8709f6ea7751f30428dfc58045c84995107ee013ca4a84f65b99adde1abdefb5428f834ac8da04dafb9beaf1813f73a4bff2ec94120e3a702aed1184c387ebda2abf1959970724299b9a05f4ad313d91beb5344fe1fe13b3fc3386c279f031c77d74bdc9bc97e22455
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 18e158ea033c33dddfc57c8d6c8f132d9b129aa64416cd971bd3119ae1564fcad726028278288f6767c0d6a8a73906840a67b50dec8a302c20760fe62bf10dddb05d171a2c97a309e41e43c51b787a9687d1ceb906e61e5f8e2136f76205a1b08ccdbe3a875017cd3c28ed6d3013186cfb990e30fcf041374b1cae57ef5ab24b
+S = 3491d346ada87f5585e13c5e3ed29c35f7f8536d16b99a57e3519c6c0fff826e6e314ffab85c3d5918473cf49dfb066cf107db8398840c53a1582a2bfc792c7cc1b72d3ea0a0ee0bd9c5aba576a9c1a41836caeb61da3b019fd553ec455b5b2c66da6682595e1d2731135ea8681e3d0b262316763f0840f030e6e26c67f11c1bf93dbe71b82d593bbe869ebf8bebf831e62ef31d2851469145a1f618734baf114716c0949a28a27a83521b5c68bc5b11081f6877562ed33ad603b436b7a9f98dc0f2968350810e24477d87df566a77f6197796a835b1945418667596171868a6b14d0617a2d76fb85130d8f5fc397326ea5f43587ce1812eb86e1aa584bb936b
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430cc8f60696cd0d4217858fd042c6caa3350dca7c9e36ad539e96052393204ff21a692e6349566d013a30f59c2d6bab449
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = daf4399ffab3de496e3ec347b4ee6f4ebdbd83cf434ea81e5d2dc6d351577771a9fdbb458985ed913fd2f5ea1cc5c0df8203eddb3ff9c94d191e7e05aa7887e16f6267aa1b8c9b393143cdded1f34a02d2eab60a125eff7f0ab28f6ca6f5c60853aca79559d1d1886b1bb1ea7c80f7fed5f94624658530fd587061d0ebd51a2d
+S = 091d2c61d369410e236653b2b1b068cab3fa6632220f72737520838b7febc00bfbec8e993c3c969d7d4825ebf03a5ef7f087926ef7316f97e57e515f9aaa76b3a7bb10e64d983e6c443906882028dfb7e5fd4558a3f24b2c3b863174b011e8587995eb425d52e95bb27f98413cf2a1f5999990df7f5d3835aa19b93fae1b1734ddfd2be99b9a5a071d062b707543b47aa650faf640afa43a51c4013e27d278557d4429584bdebfe5fbef4c9bce178a496c0124aadc24d9ee8af3e0e83ea72ea93751eb687875902c7348a212819097860041a9773d810dae6d3c9eb6049ffe38e2a09d976cfcd3dededb7f374577458b25124669a85de7465b8ece756633c1ad
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 6cd8ccf65bb3833c81961801ec68a9735fefb8a5f7e3e63c0e47fd6b60f934216c87af801e444692aa9b8737bba4fe62cdf5b485d7bbf54a2e095684a66ff765facf06f16e6c84b2b2444cae0aa05196ace9274069bdc5579042895210ba7ca2dc58d8309452c70661386e4c21842a77c47219bdf512ddccfd9b9cbbe5024b41
+S = 0f8e07afaddf2b88cd2ccc2f720228e612ac00459aef46f9605cc609539097e60b10c6507ffd3fc27a15d348398c573bc8d385edb18fe0246af4c0ab32165f05a0b641d2e016f562397d3080d602d9c734b4d00b27f8a016f58aff098be7d09498b8e1775f0d7a3f69c383dc1abb2f177fa53ae8c5425a82a1a9ef0b428b70e48b7bd99df60ee016c4bd02f428a19225d3cba5e640d297cd28bf96a45cfa8e4e222e245b55a5528301d71e12b70246338ae0f4754b74a45fb670477aa1b1794ca1067aa1289819290ac7fa23bcea04442fd2c5ec835bb4a2d007fc2f9530995409f1e707220ed5b845feef66537889c85a89592d2df941cb61254b7d69ade808
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 5ba7760eab59b0b7eb22f2542c627352ef1c75f931f06dfca949644e4bd79d38104078a9f91296cd52fd3ee0343f00454d5f98d2e31e156f17ab3adf671624dd77072d6b11b011676a004f5fa719d2a69f05d1a7e3a4f47afce9b8b5f346148517655dfdfa1967adbd94ed778dda329e6e76e920376b5246de6da779f651b657
+S = 8385a5fe194a10ad210c8dc069899df18ba80008a47f0f8479aa690eae5588c04401b96afa0d8bd6512b98a46d137b32b48cde633f04604f8f08f63daf4f35b836374750d08cd20d4553752d3eb5d27da8b8d12e86cb81c592d39b66ac38c04f0d5140039f165ed670b3757282816f6b607e2708e66fc699dff5e81cf2861b64a98b572a5c417056fee1335e909f3f7b9d6930f399c29a92750b486263081e6ecc2a2da06dc1883f687a9fd480f4366c3099c7fe0d56c5c7a70b5a710ba021c075b9ad46e741189bbccc4f4ac936e71121a3c62c577f8157b1919df586569e6bb52158fd0f8d08ac1114981f904b5f8b267a12e1098b2f77918ee9189dbf29b6
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = e703433ae230a79291405dfaf58386e63fb5028088dbcda5c26e8f30efbb6e7c918a272461fe5d0d43bc31a77a4f126f18ccd6b9b9b10aac7113878e03f946425403760e1f4fcba2e99c185638b020b400f8aa365e6fd35088c0a8b105aff4c719b5578184ea98586c293c90976e58bbdd82a380dddbcf9af0bd1a235ba62013
+S = 25181c5f1450e2179d3b6ee166178c674fc572507cdbb0aafca5da9b54f10a3f223670db1122140887e68b9fe8365f316981b3d611157e2d579873a2292daab5e8ec6844ec58021cd814040cefda9f7cc3bed4eb0edd3098e3d9e5546060f19df911f1f89b92e82dd7aa118623e1c707ce43a2877ad085527ccfb5d5aa2775e089e606192f785f3edcc02c59e28dc9a9eae82647e1644aaacf05c91628b1f9cc55c683ca5e349946799f456bf8f2e943a0d93966521e2c35e294ca610dd93f4d871cc80b15bf4990a0999ab392659cd81af705ef0a3d84968f85393dd6a53579c3e463ff2c08b9f68efd4a0cce43c8118fcb61fa2fc47aa9ccb6ec0453b7ba51
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440df5bda9e56bdbe752f0af28644291a8d0fd9925f8794a485f27fdd5b3c603ebd68742e334ece1969a14dfd84e782e5ee8c8836b93aad629c63c826c84cba848defefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 5cb7a0a74095a6f284a13d4392aac30a73a9211df0520bf2f7e9831240579fca2f7d8d24fdc8d4161306dcf8b678b13be92804598f7c7308d10c0ab3bfb1092a3adee799113498b76a500c3f64e8f8a4fa16d8012bf3354e576823daed410ff54383b7edc5007a3d5228d200e3221fac6e1ca6fc0adfd92e53a6d96f10303994
+S = 25b408187418c512e7d36eac17edc64999e94011b4d5088ab926d29e433a69e24ebac43146a1371635fc78c3d215a66ea46d0a734b1607fdb9c3848a1404545ff60582abd579d978902ed399eb5dcdfacde0ca02145480246e1a22af5ddca7080aec216895d3528a8756e0c1a2059d392f87576fe896e411ddf02bd6be81ae2a654e0a15542a6b533b776703e2057b01ad02f5430d97c691f80219e46319de527541f0bfcf0b4e1b510059fa20779eb44b1ef293b7a8318447ed25793037ddfd1877cd98514c81575613f36d946670f632779eaf629a593fe99110e781cb38101a3cbd54d7871983dbf868a00cfcb17bd330309d43b8df8d4f05eb4c43649cdf
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 290d117f97d672f3647c2b24402832b153d22a25820567688645ed95ffa6e38d116347486ab4b485c27aef4962653bb60257ef82256785a1d3d52aa0e0b94c37279dee7bb308688aaee98108de6f1373ed2c12429c9b8770756c12c03908b346b129f963bfaa38a8937190cc656f057ef1a812dd0312f51285c4f46f9241f3028ea6a61db0e9255976469f5d5542ced55ee2d6f4afe766c0a70f49871d369dd8f3a82a7141639efd4a1f4a4009821c3c2b9f5c5f5eef99a5f00fbd8bc8191a3654e8f8d8ce12d90e5ff2a4c530b76306c8c56e0549a6f277ab2af3a60cccbf4bb4b2cb47f04f211f8b86aa653bf6913f3b5ed190c51b5958e40597a2dfd30061
+Msg = 1d9589c9227a3ebe444b5fdda538adf0ae8f8fd69b30b58e3a41fb91ef229065fca3576fff758d09bcdfadd41db2904f777fd9a90f0790d4ddf30ddb90c61875d20f4edacce3c7d5ed8af51be779cfdbfb802f96774579317df17e490529a0c6254036b391ab324d5eb501590b74b2bbc1fb5b45dad1b8cda1a2168258356f80
+S = 6eaf91209e0a5f7d985231c7226732f64e2592e6be2886081f830119018ee427b3293ca3ab4156a41684824f26227401f1b10f7d993b000f3bd5d82d831bcdf772137a2982af4f1fa2b57b49833b97f448aba20458f3bd8417872f7d6b6156300d87aa87f2aee301ff53b6c367dd6907b61b6336d1ac97c4aae90e7919d94b1cb0d919a33003f05f941339f5c7de72ca94d9b65d42176deb086ec259df9e29675c087ca0d42f51be4324f8e1bff094a517083e51794dbb68aa229f7c1560945142c4e66264cf8d8fbd43dad4de21b96522f4ad7d1d121fb320204b008ccef86a22427b59b8e58d7e44fad62921b44301249fe1139ff656fedd466ffd46c27703
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d060960864801650304020305000440b1601c43923bb80b35c45d083bd748d75a3fcaff22044525ab82d705d5465863cb373e069fa40c9b8e5aa4d5ff7ad45700c7a8da342bf0b16686db87fba0abaf
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+n = a911245a2cfb33d8ee375df9439f74e669c03a8d9acad25bd27acf3cd8bea7eb9dbe470155c7c72782c94861f7b573cd325639fb070e9ba6e621991aefa45106182e4d264be7068035595d7549052989b3e7fd04cabc94012c1278a0ef8672b1a51dd1a9e276816ba497dea24b4febe3dd8e977707bcd230ca6fb6f8a8bff9e6ba24fbadcd93f00126b19b396a38e6ef86d18fef945b9154c1963fb488c7025953511f86d05638bfe056493730bc6778446e59cd3c5c3acf07a0a3a64943793652f10e3292aa7a6d25a03181cc6f6ba0658d909e59ce2a02bacc9766fd8c4fbd4ed9c23a866844b8a794d49e505f9f944870a71aadbe5338039825c2dff81af3
+
+p = bf96de108963b5113399b664765efe046e2dafdb70d6e5e29dc6ec89b789b059348d74d89129c7ade9ddb404c6dc3a3437c7fc9f23bc38dadc8ffd0ff757999f5c2d510b993056147ccdf421e03d0be2c74ec333a9677c430cc604f5550d0d86defdde71488e3db889c699a5cacb44dcdae2f3cca38695e783e6f6250827efb1
+
+q = e1e7e33618d1b64d6862c132e4b1cd5fabad20ce62bd97bce2a3f5ad2da67bb0a7f0b9e48335a33b7b95e77ec4c47e91416881f9f7c23f9bc1918cc644335c74260e90cd7b2e0fed802f19e78c5ed80a431b38630d82f982c74a0381b8ecf943c60810fae90574e216357b2535002316d9529cb56420f3cc82dea37cb624e1e3
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = b756bc9af8682c9473fe98082ecb72f33f6199099baece582cc6672924e3472790a90dc330af8cd6863c7c882d4e6e726ce106ff0b6d641865b1e300bfaf067cd8f8af38c1299266efb6eaa88fe66a30191f772528649449891c1eda921539b6b5c80ac255df278bd7f44b2efd9c4f766fa455459b9a4735bf8f807e441cc81b
+S = 20aad3d29d4bdf75f18d3617771723419920e688928a0c742af8b11bd2e05767afa0256c868c3538111359b7bb91dbf1b8bfc383a1573cec0bf0c62837b13fb5df21e7e07bb5d758ba8d58171d22b46147d6f7bd3b8751e97ecf13a5bc8c9b5ef7f00702c3ca400b6adacc6de96779a48881fd7c3f544f95f99ac1037f6b9f49c308aed1f6634afcbd46dd6fcecc015fccc24716cc590687fb2492c96812c9ac037f743e3b47d60420ee271331031d290fa6179178444256acb5697fbcbfbbb4fd3c6227566de99b246a8914721d5dbe58c2411df01348b63bce4e3659ae7ad09579be43acadad01ba02eb4c118b23ef64b318c7424920c5da7176ab2cdadb84
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 196c5dfa45aa9b9d8c8f0459ae650aeb45f1b05e06a6ecda44194fbdb5b5e7ec79b0656c583d7b2c4c0488253fcf77a51586e4e8ed5d81e9a44cb9779bc0938bbb90d8d9b63278a58f2f2ad85cd453534b2a2983e32918368c2965ad529911f2e6f3006ce5ef5ab05df8329a8edc659dedc7c5576f72776803989a8560aa29c8
+S = 4bfeb7f6d376548f1ada66742eb2320689db85eaca0f75845aff7cbc91faeb1efe96ddaeabf8f9bf2b3031aff3711ebf9e4bbfd46861a8bb5107aea784a78205e067779e98be0a74458c0c850903f58dd3541636c2160a8854914798310324f852c3806f0a0e59ac6b5d3ccfd2580443d09752640e27f41b1e692b3ffec67c39868f4605230b341a2b56ac68bd2fa3450df2ebf4867ac0156be6513e03bab686f435c931532632adc177e95971bfad056424230943e5757d0c5384671592b7b0bd4a454d4d73bf312f4f46f2f310e897bb657be3165d040ff0d8bf72315ae313fda1052c37307a31c2f8d4edce4644b5bfeb5ac37fdf0e2a393692dfb72bb4ea
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a0500041476e8a26a34cb08f8f58253d073c53dd76a749c5fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = c0b251836d180dbcb995b4ae6e18856be5e8bf067841b753394226efe507c7801312223eb1efa2b3b117eebe001676deb8e94cad96aa36abae6f013d5d6f18f680665514e33b164efde094cdda7b707858c38f7496ac28ebaa461b0d92e285556d78910eec45911503b84de0e48f9abf2d3e2f626090b59c95901d666baa3627
+S = 0cc0b5e4251083e72898e6d239dae55489a42675123fceb8abf34886846e5af39d109fb65d55fb019c43c3fe91b891262d8ec0aa721acd97848f455f049d6af58b5e579b92208fa48f7afcb403dd99870bb25a15b33a67b5a1ad10ccf3df04fbf5fc42a2a0dea7b6c689d18da14757b2b5ebeafc39f62b5fdbe58f44f03e148d4e5ae6ce1bdce9f316daf7722ba6622ea6eb964fc3d0d9ab54ac226a3371ef96300d9d737767cbd04963015781d14d9f0f640b1981219d391ae1d94eab184d68f1764e7dc2aa2890b08c16ac277aab85e2912975702ca0834ff7026be694f805fb2692a605635a020018342dd89b8a53f8b5fc7b5fa8b13fbd9f8b5deebbc199
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414f40c85085852eab21192fc3cd95f0ae92a42c3cd
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 9df2b3e0f8035d92193f0c980e8ce31aaf7218078171f907da982db246533dff2a8553ffa7d641cbc14fc4bbc1240ad8d7d07394046795b9372882a0b7524da3c03acad4719996f0e62a578ea175459c2ee5ea0c062125cbb59975f3385f7441a939a2c91ef464e8cefb4d7b75289b4efad905d84f47b4259a138f139222bbc1
+S = a82261947dd0f5b3f34197bb91401278dca36b759a7402ae65d8db6b6a12fb2bcf67e564d16030fd1b7e4e4df9bf0577c5dd5d6a5d8766009277003d0e7929675ccdfa04285e74ecfa1a937db117a130fe4662da0a869d7d34832165f86ad8c345cd6aa027036d818af45fcc8fb7bf55975c948af26ca363ff796c752afafc8e5afc5ce5208bacdaa98601046e69e648975a87ea34b011237bfe5f734d9470bfe71cd5053e2831d321fdb13e2a4221f992670782b7c584634761b7b96a28e33b69eba97ceb45aa1adffb29fd4705e4532e0fe1890d1575b5e43d4aa294c27936999b413a3086b000050330178b0f71248a0a92af444d8fcdaa0237b7952602a5
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 3f3544b53b09a91b7f1a27d5fed879788432e604a8b6d121fcf98ba886396b657441211c0b8d47c9e1af392c4cf127851a3c689d823811055bb5c7a28c4ad16ac43b71686ba07506d8c4098bc4cccfe3fe99329f61eff73c04d614a8b040c60297eddea1428c5b59cc233ef94eb09a189a11eb122c21a84d5d241cc1da6571b7
+S = 8caf5231442d5352259da89fbf54888cd32774b7851232b21defd3ae6d780a5387ec021f0260cd299ced9fd814208d1102620cee37b2d48b5c9ad90c061f0c2a527bbd1eabd7aa76a5f4e083483eff1a9b5d62dfe57c751d9bc49991485569142c65656a67213c37907db465dc7225c7fcdd7b9a37e3d6b887b07c3dd07dfcbdde86baccbdf6fd13676e062f9f875f912058536fbd31d4dafd9c051bb79236e6e0f90db221acfae0690b6fcba1cd7716145afabd39866e393dad2ae99b24f9d97682e6c1163f5f442c4e49c7422923625b63e82fb1a3186fcf0bb81ba38d6761156b1f723c0de7fdbb0c678effc49c128e655f36ea465d41e704ad1b449294ef
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 2726543e530ab04b06a11cbae1da53aa966dc51642d390fcfe95acbfb0ca65cb28db0f77688af52f423392d2295104594143bdbab8517c0b59ea7beb5e2fea1e86b69d77688702fb076b5543a6671722de83bc88edcfa4a651a84c539638c6af6c3c6606fc0abff77cd2cdd50124744d95b229498a58f0150e5986c0ffecdfc6
+S = 51d57b3e66fd6e271241215438be99969c40d0ea4a5b7c4918143f68f58e5cd9d52d90159e7bdc9b73ac3d3d908cdda5e402f0fd352931f9bca9dd886fed30c791efd2466dfc7c6483aa32c2865cef82a40dcf5c5bc3aad547b8e1dc9d973c8b90f529ef272a24645a6b76887925b6e19970d9f2d7d68a513f2e1638b184aa8cd20967618d06662bfe1450f03b72d19790fd1a591694043b310d982077285deafc28f95b3c6218edf59649b38e9170fb3f18483fb3788a14b161648beb4ce471c0ba4c041b87e6b38067fb934f50908b755bd126d2904b75ad7ce75a8a5d0c3540e1d9c7ad52242f2e5a5511d46ad8099f9386299f369e69e53107c6f51fb985
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = b756bc9af8682c9473fe98082ecb72f33f6199099baece582cc6672924e3472790a90dc330af8cd6863c7c882d4e6e726ce106ff0b6d641865b1e300bfaf067cd8f8af38c1299266efb6eaa88fe66a30191f772528649449891c1eda921539b6b5c80ac255df278bd7f44b2efd9c4f766fa455459b9a4735bf8f807e441cc81b
+S = 3840e121a02c4d4dead5197cabbfffd00005c9474df11252853dde2cb83ef772e2a533d7e51cf524af80d1a541994018abe93fb5835989e870ec3400f171ac786678fadd6e478ddd2d6f95719c559d737dcf2e5fa0b875827ad8558c70f6b8ab725d7344ac5197270e494ceb03b89680b8bf99ee9260cf91f0611060d7ada8d2c7eb672a2957fe4eb1d3b027c4062f2d2d840304e4a7faa243b816b10bc893b2ad48e7ada998eabd1e9fca72c0820b9b4feedc3733d20087da09c26e352fd7a4962c707a7ba9e1f66b18ea89d96d0059ebd13d177bccbf2d80a502a7362e198d7bbe1199d5587c06e1192ff539ff5276ee5ee8ffe25df0a1998e5c8ab05d3097
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 196c5dfa45aa9b9d8c8f0459ae650aeb45f1b05e06a6ecda44194fbdb5b5e7ec79b0656c583d7b2c4c0488253fcf77a51586e4e8ed5d81e9a44cb9779bc0938bbb90d8d9b63278a58f2f2ad85cd453534b2a2983e32918368c2965ad529911f2e6f3006ce5ef5ab05df8329a8edc659dedc7c5576f72776803989a8560aa29c8
+S = 411e75af44716f884c084569a3500b74017141ec3f1c2768e0720d3df6cf221a155812756068bfdc74d998743647757d80e15752b0df1ed038ac316aa202a5eec1d0363e773a372d9f60c4d5c585f1111ed44b02c241280d2b6980b2cbb09128ce9b6ed38d50dd0ce10b73961b82996bc82a48f0d5a574910a691e55048136ce8f3668cec4cebe5c791d6b66b6c54617bc70d0d578080f22d9ed09030887bbeb5408155187a03657b55680c614e57c2e28e2c837eb7bdbec6985af6b596fcba378084d5f1a4fb80ec426966d9a9f914431811a06133c4e6df7a48577e16a8b6cc5af6873b70dbb5ef191ac9214866e73f0c99f33da2d21d313a6bb62cf03ea01
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041cc28faf02c47ebeac647f99f7cffeaad70df6513830d41a12b1d05b62efefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = d699ca7f777828b13679a9e2ca89568233b8cf479d90462186a5ce71236ed6760053f007e807d8880418b11746c59106090f408ef1133dc1199602c16de2893054d10fe7932718eb6e24b39c0f5aff302cbdee60e5f94961eb08f516e70374841a38ae86407ef2c2bbc538dbedf1a9e9e6e961263fea73e945222dd95b7a9e5a
+S = 01818ab2f8883d5b580b7d7fdd6bd15cc59f59842dd14649b27aa0aac3666562e4ee8a716d8f9a6fe19bcb5f505956457fbf200b8f0121a070788a546b86f8149f0aa98f2c6439412ed4a00114259b348d1f9e583eaa54fbc384c52c518159e460582051afee2d4163350bdba58112bf0fd9ada18346891ac14888765a68d3475f8f8f92ac9e5f4b02480859f239405d8fd14a05ef95fe9b726affaef8c8d54e6cc3a01a1399b2c2b2eba18b7e3dd7ee337c0f108dd53c460112a58f7e6b09db540ebb72fe8e3d1afa5224705f0159aed4d94d4ec0711e58873682199c90e9aa0046f81c3faa3fb21a0a05991f0752ec7e1c04d9009fcdf69d68098f9eaaea6d
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041cd8a970b5e7e41f37017b8160a04e42a8bcf502522a1ffaa739d6cee0
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = b1d87e6e67cf95799888c51383d6e6cb4fd8eecb4d2959ac7e58ce8f5598ff69bdb8d19e5e55bdd21c4e75fbe178cbbb9d93cfee8b7d387fb5a6067fbac46578cfc8d3fe04108588c9de077eb009249374f205553bba9d0218b2449ed413a142eef0ceb7e068b744a420c3c377f1b7faddddd729e5484ee0ae64cf132aee7d70
+S = 3dfbf8cf23053223500b1cc0a4e43e7754f3490f33648064bb9a806d17b8412075997148a76a152e7becbcc26783fb0519df481711648b35ead7fccb9937baf37e4b86133c15ec2ba0311ed6cbfb742daccd68bbe8f1b49766366da644302a04ec1952db9fb8e50641e3b0cf9c04066f5d49cff593581beedda78e50615c5f42f31444462f59e1e3a8331c1494867361073e5ebb8d6ecbc5b356454a4d24d87ff4dae556442384aeb0cbfadb3437074a76969b8f213a4e8a0a0538114888c95436582ecdae288c4f142612e5ca9e273da165cade52674f7668dd170cde6d7f8e6c02cd1cb013c87ab4a5c71f9f04c20a0fee617968f4862a101726368a96f3ef
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 51a9457af4abc1b75f3bdd4a383b7ad79f1bdcea045b15953b4bc15ad216f44aa2fe716fa4e91d68061db3537e48b8f0dfc3b202ea1795f966c17ecf7332a3301b1a8add2ae67a523f8730a72476d2b45bf52978f9970abcb80215f347f4a365e484f98c2dabc2be3302bc0dd1cdb16c3c39a913dae25e245898f08ef763da31
+S = 9c7b10642d88022ee6cd2816c95178a5b163ab887a3b663c0236228b72a6a92eb18d3a0fae84526f1e17442a2dbb199402693f166d31d30105b7929046db4b1812cea8d7a1c5d5d53f785130cae9816b8254de0aaaeecac2992a1df4796dd423641d685e65478850a59436aff0f0ce36f1d3111719255dd376d8315905f4b3db7439ff2b0fda6226ba64df947dec832db48905a3f2d0d9a2b46f92d91794ab98734e0a7acfa0b60216f728a0a4f6c3e188978cf745e620cb3a0fa836c1a548e1b1bd2c03926473ef6b145d6fd99eb5d512632334a2588fd7b2640e0d893e6fff31350a467543ec4a18f51853bd4566674bbc2867a18de04953b1cca246a558d7
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = ad32c2e66fa67fa97cbbc8736e36a04dfa8aff5f734c75098fe711306e9181d6d87e7aeec7535b6e25dd0da5d6032dcff9f96de76bb737bc8daa944748a94d3c4e2a50dfa2b654195a9ac0cba4e0c962077ddbacebcc3bea5c3bea260b45ccc695a0096208b7b4d3a45aab8cdeb4be2eab7e1356fa73c8b98204db74bf4c479d
+S = 1c0ee89d483230cfe29503591c7d002e1930128999e06dab41d60e55ed7fb191b068b2b7c606e0b684dfbcd7b43045f10cffd72e96fdb10af7062d1e3af334b2db7d79f3ca478ba4d21f4e2d9aad635c47c15d26eb86643ff15d5366074d009bb4e213902f8c4ed53f5f3c2e1ae0771f0441f68257aa9705a4044d6846103c75f83c96f3d23a450681394e0f6f816fdc5545d96321e90a4c0a90899eac77751933f502c4b6fe72177ac1e9d3f3a67b9db66b96b78361ea7c47317b742d6f6a941a55c496cf7fcdd73ffa79274898081490049612f580a8d1e7edc95c10902dfc0826be1066e489912bbdfa2c8d6142ce9e1d3dbd8c9a9b9400f39579589f003f
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 585e2aa15bbe0f218e5119f95a252b57ce65d9474d35c1c284de1ee79f2b9a88bd1364e8a19783c3aaee6a8f05e0cc022170b1d463bdcac61c2a01e3b8bd550638c5e59ce2c04aab367b2a14257b0a157e9c6411a9f8fa94970a6992f91401efb0bdd44485ff0de11b40840e21bf8f97cc321a8785aefa33dfc67e7acbf7474c
+S = 2e02460ece0246277d4517b9c00d40ee669251ce1be2d8c13bcb67b7e90635d6a68f8cf7373bb5962ff1d182f3fe706ae3e216446527cafe5e763432141f92995002f6c6c208e85ca3203de5d6602db70c2302c804abcb7b3a22edbc120a3b59b1febfc485bd787ff0053cba05d27800ab41bb431d9b7d7ccf0f1a5f52eda8432fc70d1bbc5fc766b08280124df71d7432542d5caee7d88db6654510ee81c3cd23b1501679a2fc2b050acfaf9218d7c6d4b260f9e8b986e9dd9c158820379609f11626d6b35eda024aa545286e884b6e135ac3e18d52c9be687004f0a81fabcef972cd2e82d954a43ace6f1971d7311ba9f267b262303cb51121fde66e073e10
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d0609608648016503040201050004206510c46f56c48ac0b28992c5bd0fe4047d3baf1fc7e528f67b15f3b9188af1a1
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 790ba59678e1eca8ce7e7723488b181ff1fccb3e339df4df3eede794ae30add767c006f8c4a4aa5af263d4df961a01a1b6cdf5e3d6fb004761757f414b70a5cbf5d87c5a51e7261146f7693556946be27ed6b9fc5ded8e6799fe537b7f2e62b2e9fc0fa465d3e93693df3d0ecf21dc4a10be1e71109d27a9ae30692b90926af5
+S = 91a2efacfa4e8642b683ff7c17b08743f8bd03950a35ba44372ef1814fbdec087c033d6eceeee431efdc6a3fac97f85b8248a92b601dc4ea9e02a23fb921655f084a4035b42c0e491ddee05c4d3d4024b6446caf77e917d28453640c0af50d937b5d74b535acbb3ef9b2dc87bd3cfc80f24d2aa9b1feeae7b549c197cca6888fdb617c8a5a1c91a23c6299cdd1b7d292b0227634bdfd415cb6f12723fca2edcfd1176a485b2a2cea075765785077c84de1c50da27daf89407becac9fd9664f2547c5a9f66c9ae3c14ce318317c58d4c3d3b07f07d2f8a58fc10b854b583a628054cdcb9f7729e5707d151a4ba82b1d99f339d4f8a0674f260a8a6b8665169fa0
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 4cec86b6da42bda1aa66d9f6ee0ec6c30f4f575ca2bcdca198d2f67fb494aaba4372b5e9076f1fc2748313971f3eee2173af967da5840d74eb7246ffe9d8370a6c9f2f795b646a69ebd9e3b8116869c73d1af57e45b83b919f307f02d439aae8313a9d6ec068c51e772fef60aed45e3dd7581b69699f8d811dd249915d012bd9
+S = 89a014c41636b64663cf381dcc399355e2974e1db624e36d5fda7d3967417a3810910948813ea58caab8f7cf2dec7309d26d5cf7db0dd60a0ff42982b91f64f17cae9195f2955395e9ddc7335c441de9b65a0e252f98db17a805ffd0d0b9a68dd6be098107f1a6f7cd1292b2d6a9c23cd631c62709b72eecfb9fcaca2a3ff036984bafa785722c3fdc8398479ab77a3e1678c7af85f75f7a2f4f54a13ecddbbd4aeec7a96445c885d12aaf236a9c4058e3e669335f5fde34d6905bed45cd741d9a08f8501706d03c7f98b2c7214eecbf4759d661a32eb9c302a9c0057ab734b46dc3575ab42951298b59d3d8429339fb58bf035173a84dea90cc6354dbf68d31
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 13f936517eac73d6776695c1ff3051850e32fab734cc46c280e355dca079ef3949810e7edaf19c783c187d0e0c32d074fc3a72a276ffc405837aaf74ec5fe5659ff26961531c51b56fbecb6b28455e78ea7f7237faad131659d9f290eb69ac5bd8f54fe233561bf5daff85bf9d9182f9a2a9015e07fcb95fcaa72617e6c0ce81
+S = 2eed7fbbf583693f63e22bf78eb4d389064c21c37b66667c1b1994934bf9ace14c30279253e9195d176535e28aced6719292b064f2cf99124d55b347a14c960af52e912afb53356168d1f19727d19b65c5090c4db0e4fa9ea0ee3d3f28ce0a956f7011765bb5e58a14b8854e58e04723bc73de96278c78efbed70ebc8052d3359ba967dc91b1f982932baf770d2d2f252f37d274b9131e8c5d4607b67115bb18200a2ead70c6882ff721284d0d0876ee85e68dbefd4e3a9d5d898aa9ee6d2195c822fa02d74ec85d7a93d9688fdc5fc0c93d9c7df6c1519ce1384174e2aa5fcca3bf92e260274f2e0430ba4f008928d6ece05f0ac5a26683ce956fb7ed43f7b5
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = c81e98ab21239d9d887553bca6ecbc55a1e4593036f8e670080d44ba3793b79935075121d5bcaed3a5dce2c17ea9b0f35909fd08644283205602cafaffa2545a23ab18ae889a33f04ee0d9ce7f2d9109e7eea21b2615c81c03182ce6033c93783b13d698624392bd2a8a202bd0ffc860f29b31afa2f71c2bb85752c66ce8dbba
+S = 36403d0116aa5bad635f855b1aba7ccbe7787bac4d2d0678fad33163c6a19e88fa53acd13646466ba5e11668752f52ffa3333c59d9e00bdb9cbbb9e549a47c700b1d8be5e1a778056bbb0f4d0a3266cf5b78b2c8a224f460a20b31963105236decdb49f4bd3adad75b6ef5331cf0d54c91fc0337a5ea3d1dc94e6182b11d7eb6690096242d84c174a0c01869c81b193156a730ed08acb516da3a2b1646da3fc8742191e3620d813fab2f4288768388b5c2892ebe6a42b7047401437b625b7d87368991020aa1f4831088343c51af5217334f852c49b474fdee6676cbf8d78018061bf3c398a75a73503e868468136afc187ec1deec0e2a852b454befc60d9873
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 796a46d728d7d9d6418710970f311d92f5362862f71df0d47b3fb63e51c35712f2cdb8b205f3668628f17e4dec9dcbb0211d2f1d555744d297a9423881da2473755106372685d2dd5ab51bb6efd9499f1cd8f7d5fafb990b43a262ba593665b98a5efa0d92766302613daf7b1fcddf866ed14833eff238a70792dc6ce3bd610b
+S = 94c00c47cfb2eabed6ce3b04f88e797b1b2eaea162dac2e51fcfc8b9f9242c0f48f664f0b65ad4305867758811fd1cebc244f026684835b451e97e6806ad2427700f2d9c12f681b2d601fb6ead7953209a0c47db678ce0075f34705e4b1cc414f74574b4028bce76a69e160ae8180710b31d42950b66f70c6c28b15dbe38915e8c36d7df03ff5494a1265041a801c5916ff73e08bceb792c536608262d60ec34f4d3ffedd74127e9d5b237af1d300ec58bd4475f05c568978860804818fecea2781c96752821cf22164b1b917f3032c58cd47996e3ff5284004723d0c27a3d6439da0cfb725b991601a801c89a77f2ba174e3980d7d3f1b342c4b6cd16121656
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420e6689fb887124d3316d9609e412b959be86b7b02a1be76f300ebcfc82701a77cefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = ac481c957d422abb5ce8a73366bba51b4b718d83ed3c59d22a4f0464f59f3f78ace6664aa5eeb27c0b0cb0bae8eaf29e828a04d1eb88a174d4a027bea26f49e6c47e0443437cd4b29acb2738c93f12e8a5224307727b376fb38fad3141a95a7e9b17dec87d75f724b42ef4f3303f6dc15b3e326da99b818a70277c06fbd2d909
+S = 3da89b974fb03b26a5617a391b68413d62d03b7cf27daa0024e7b0085c1f542bd82adc66102c16c57c7765b1bee5ceae98ed54fd5fbddc1dc37a3a75f5695c49dc6f026213f79cbab37093a9549465370b7663f363a232c81ecb71074166bdaed7a558c5bdab0a20aa7f5c1eff0258eea42374ac3d4b386586fda7913305a602c33b6ef6dca0718fc330530e65f44d8824b4d1e137bcd3aaa9fbf0e4079cbb02a541971ce5a25d8aa91918576bdfb774ba70848db5b78331c71c26c0682b812d03197970e481689c39c56bf1bfb2d7f4c0d5c8bbbf5b3b6537f48572d5f79788362a0a7172f20308cbdc64f0dd9d0416bf09c608e915c070f4bb444e3b7ea492
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 8603abf63e1dc6a957770c225394c0223874b3ccf069c315ee26a2761519d9e3d5fb0c0197a57f945b25d9369f11284f831b26412ce6bbe36618c2318db11042ad9bb27ae881770018e5af72b66d31d8fb7ea3d7440cf528bbb12f4834fc6d70550b27c7fa5cb6d7d7e0143d6051e4a5e5c6b2f602857bca36187021d2a3f756
+S = 27d202a060e759b168e451c6bda8a290ce96aa70eaad61e65a37962a766b851ad506cd68755341f4ce2858c24c27953fc8f85788fe77f90d17e7427f6e487ee4e41bf64773c79fc1472e89ef66f6cd532a1f485adb2cc3952a15e5b93eac7cb2585f03206733a142b8ba9465653e02843eb5c70ce8d7b59fb3b8cc2ae8d0405a714fd55638aca05b0bb3b5dca25dc7230eecac2c8fac049a0891e1b986308814486dc9d076b780b30f1c2a9b8292d2e3c56ab2980c3b3cf87292a300924c30bf2633f272deb8ada1149d3e347f930cb5a4c7db035352915b031f524ff07889e1abd54ab5ce572c63d0ed3ecbb522e7a4d087763cbb712eb44ff81ced4a9ccc3e
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 44935b571d8e202a7c257defda42c57a4cf3deeefa104f7fd31e9b7c7f73ce8c959b55380ffb12a9fbb4b0b373ca3413ce86d5f518180ebac081f1f791b0bec1e3ebb42813712701305ed3e9f7ce7086024587103c4f831098630b68030d8f94974d212f113a87b985ea8e975096a15b4ffa99464efbd70bc38c90d6bdd2698d
+S = 64cfae08fc369c5dac6c08609300ad79ecc260f52cd9ab810d536f776aeb9158e8745474c76ee9119ad1d3780f0175bb48e239998e0580272417f9129fc778f5679d277102551387e23ea1b0602b6617bd323deffb2c894e24d6ff5de645efc49e9165a8cb3752dc59f81e0e205eda79da7dd64baa300743919969a1a3313c2e5b211d9bb3627cf6cca4f406481b95bceca64c733ba51a04bba15c7977bfab4a776009b82d152279bca00699c91d9bff0e1f78e3a81e52e2367c982a421cdddd7dacf0b888c36d7b9ffb3254f8140fb6aca60138f196b1c65690b40476a371ac2f62899d253e730d60bf62559fd4aa3196098a0ad53c98eed2a0476a4b51f264
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430bbbab81643e08d7a9d84d488c6845a98389c05737c2c54103cbb497d3291a181a2ab6b4e5c376b90bae7af4405e178ddefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 69ec7262fa272d2512fe9281a0aeb2ceeb77a0692fad31618b0cff731a4cb43961f5859ee975fc952c6ffb0bb657fe19843ca07fb0e4614e501ea6e49b54011d4d60b3c84da06f588d4d61dc32086f32f6b6bf77ca8e79c1bf70ce1126793983f6d404c86fd30fd6fd3ecdde5feb8f7f088e0539c6d30124a1aa7fe206e2e3d2
+S = 3ea196268020d94c900f39ee2eca7e735e0cb478de58836b575628ef46c5e78898c2d76c7627fe36baf3eedf4d89c2572aa3afa8cb8c5ee3433e4c2ab7abe8369047d21cdcb00e1467ccd60cd2bbddbbccff5a7e0f1ed9d2d5fc4fb587d41ac538e66d9b559793e0fa8e44ea72e9c603d236f1c82c4ccf665a5337fb797b001ac0f4acfd90e54d147cb196f4169dfa0f72744bad275a748f4b402bb2cb2ca9adefb057a6400855483bb12c8e51909a7241f413ce7d84f42f8e4032acbb4a97848a0f2a3c473af3f6e218100b4d446616d55d55571c0fa9e178f502370008317456318115f8276aa1e569cf364efd5c7de9734eaa575802b0db421de6309c175f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = ab5e706303ef34f4f855722eb521454bd886ea281c677ff935b40b3cfcf7bfebcc2a7cf62ccc95f0ae34d5081724c43cbfa126c93b02c5e63a4870b1adad446a2b802adf932fa127f3a6be93a8d770e2c79a09b4bcb8fa423142de4b3228bb528e0684068041e2028e5333b6b263d4a5b8199bd2e7b0a874e34d5ef1d28fac0a
+S = 94c98efaf358dc0ac76b26f7f52b6a9c35bd8b63f9517a5b679af3cf3c48fc4ec99e5c75e7b1ef27a4dcd5443f6f4286d798cd96f746c63c290e501938196421d691faf84a5009e410545c407d920b14174e66da700b457b8a8e2e59c094e33ab1f0b3a5a954cf814da7587c95681d990ef86c4f67ef97f2ebfefa600c190a49ac88cf1c6bcc8423781117fc1686da1ed0032baa42d00fa62c38f5d3d27c355eca2f4b79b57b54b7f97c43df57b546f2391f5328ad295a16b1fb6d5eab36dcded973a7f34a0c600bf8008b96b70a3e8ce0d706d16dc2c1f298978c95d4823e406f433a48c6c98e41341704abb7860120db033591eab0674e1b2f998e58926111
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d0609608648016503040202050004306234baf47b7e2a2b38f44db0a1103dcea4fe9e2f3c6b951228d1b7bad3672f8bf772a915bc9bfc52d1e5c51165c50adc
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = d2c5b7edd8611a62e537db9331f5023e16d6ec150cc6e706d7c7fcbfff930c7281831fd5c4aff86ece57ed0db882f59a5fe403105d0592ca38a081fed84922873f538ee774f13b8cc09bd0521db4374aec69f4bae6dcb66455822c0b84c91a3474ffac2ad06f0a4423cd2c6a49d4f0d6242d6a1890937b5d9835a5f0ea5b1d01
+S = a524f38bc8b2104d55275efdcd8f1bf9d529d9565a757df8b3f8bfa067d5278721006eba463365945b81ab4a504122021f8234051847938ab3eca24f95e4aded34f9e57a7b377aa16fd9379d0b703accee4aa78a015d0986e20c4fdc950a579494c56eaef8b812e2bb0182b74da9f1c0e1e3b56142481d18e64fa797293fdbf7d8d54c44524fe6b957a06ccd292edf0e0353b96e047813662a7326c42c8bcd1d231c6a486699b756fd1c301b1891da6d51a3e5722cfa46592798e91d8df31cd98a3dd0b725391a4f9c6fa1ba312471f8d1d85519f8df7ba66244c5dc679a1348d2d415b8aa22b02a9322fd2469f9da475a8d832862e6a0cf24eee957eafc488d
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 302093a4a99ea31b8a693aac1743663b725aea8e19c1e35fb01dabb001a1fe5f413c5bfa9410add4d4272b598e617d9e4eb1203d1d890b5f4793931a62a28cfe8be8b1eaf36946249baffba95bc014c2294dc7d8982ce5899f09bdfc9c583e71988d5b1ccd90b433656b7246854672cf8a96a70a9391b9063fe5f2fcb8a95be1
+S = 2efe346135008623c56353482a684924e55455e5e75746707de371b9b14ffbaaf5b5f2ed85bd7e28ce4e1700af5014bbd315c32b872d567ea214af56e8c3276cebdb0f597a6bf2b0758ae2e5d1e2e9334a53f838c668bc9a1503010bc5cb97f6215847802827ce9f88cee4233cc80a1afca84cfcf7368e4518e157f05447586cfdb3ad9b2d79bba5a6c4f7494375472fb9075d61ff42c7816e23550f1643b758fa26f4377dff2034f5e68c5889665341d482bd4175a286022f8346ca925e925f574cc961146c4e2c3e8ba12e083a0ad31394357d099c973a9ccdd4a7a6649085fc1d4a377911be767bc9f96df50f991a9a589c5d5d19c3b3e8fcf7127b7e32ad
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 634de10919c2ebf47f5520cccd2aa37f484201b015fdab5c4ddeaabd548f8e6e6625a7d172a478ae2cc6691c5ef8bca57ea6c2a586b84ff3005d6bc360074acb97b77fa5e57a6c75ef33fdcb119c96cbf588498b656b4dbc5d1bab8d65d83bcc1d8bcf4e1a4bae92f02544a1901d1738d570fd29591c8dff8da2d3e1090b48b9
+S = 8e11eaac64a60172d6bde00aff7d654c61661c4e3213bd64b6141294b3d2491bfba0040ba09eb060a14a9c754b1b3dc74dd5e6de8185eb1cb71eae7464b1511d0b302864b34c08b041528807301c01b33a4630c74b1e6fe829518962c380de8b9094f4f90178313a7d2229a0fec1a798056b871a25778813cd70b35e713cc83816549f11717e3dd4a1412251c1082df1c03c0def3ddfdf3d7cf1b7654e5af94866392ad32330f45b7e9491a4d1cc2ad64a3b7ebaac075cb26d5115bf9a846dbc29faa8302a5f6337fa2ba07f9987ce1bc729e67fe2e8172bd44cc79ea15ced0cb49039ebc4749713343f136b7c32f5760d403568a4a6bee7fd697b82d9d44983
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = e532de1004ff3af1c5cfd5459c14e3c07acef7fd9f0d731fb0b143b90975cbeb542c1dce5a4a70121aa5cee6187d0c18f8baff7e4b76ed94a9bb4266008e84b12b2c8945c793e8ad4244ad123448515df371e99c62e29da709d15c036b8cce0693ba8a3cf1e48a0a6434db91987c99d592791b1f895a6ba0f87cf956f1789034
+S = 522fbeb9dda25bc573f9112a9f91c17edc93e2768e3500b4e2a4686c9548624900f28c878fa71336798cbe95dad6c3905ac04e4709defb972c13b6a532b0f827b86a8c809699ebcce39f38d71612ecfbd030d320d709edf5a0b7ac3f3ea49ccf8429066a679d4a9f42cf2e21bfb2616918fd80fbb7507bd301a6c650efa802cd4b139f02f65408090dde62bd825e04afc720ff8850461d5f1444bc49ef8f6f4f06e7aae64bc0f9ef3beba8298603aad62547ab8e94374cc45f7165e08c612408fe29ec242b2db649475dc2b76debb660433a2d2af7c4f82fac4b858f0b715e1048933d54bf2830f6373e6aa1ec2f460889c33b3ff78a2344f33929dac1c728b0
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440ed1dda6011a1309b31409ff9a5f57605f8a6d33d91249b0c1e37bdeb6a580d334c89f5332a598379bb1f37127bc39366b275962c3bb9b888d6d576fe89f6ed37efefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = fcd993a231000dacf06ffd5d90ad238d5f67c86a9f61ea10ceb2995a2b31a1f7752b69c0f6571b48c00b05b537af40cfcf738f57173d899af7e5fb4635a5887b3ecb922524b15e8ae3ef721fe8cf42a0d4020c5f7d9101dd3516a597502b7822e023d67ac3f81c98e0850c42adf57327f57c082bd845980013ab60f681abbb14
+S = a05058b41fa7d48c6be9420c6372d559d466a85e174c272f7394cf3896e1b945ab8941462cde4042d1da2a8b4ef11b5de2c720595855190bd113d566d420b31d51cc87365a2b8d7be99e2ca792b94ecc5364cf63be7a16aaed3a723754d7491480829c0cc9fdc1791998f30ef80291aa756fcab57ff5f3e7fa2d6ab001c52e76efc8dc18f5d5fa2cc762ff863e9d6d1fd921376a8f20d4dfa61f0a4c389e42db2adb07d168d438d1ecaf8e4d62006a29d944b1b5e5172d99579bf03addced9aad16038997d2721f365629cc5b065f656bd306cd76a01cba35c806a476f47c7f9b50d211b90d882201bebac5204fcff51a28d7b95c12eafde637bc50a10a0312a
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 55268a860d34f9ac8071c4048c4d6b9e5475b9a89da448e178bc475122157b3828158444ce016206b21237a7adcc4ed7fa8b5d079a5f07d8f619a5d3c7a6465a339cf4de38133a534eb6e3e1481a03dd7c4e3cf723b33ab5030d80204bdb67bdbee463be1313897a9c844e1b27df929622e5dde10248e860e5c05fa0755be547
+S = 7150a5c72d046e51f58b5d2bc60886be8b5d95edd49ee011986915138b53dc6f1c20913513418fb9a5edfcf4a3a9e4c6302c5bff2227c81d447334c3faeafda5ab5ccf2f25da8217cb3acfc8778c22bcd1559180260a8d9a3df3b2e1c7f1696bde815b4ada1e44b50b500a0aa4b880ba68176aeefcf96db028383b124f5bc7b587c6c6a726e2af4cad35b85d25fc158fc44d34a5bba69fded3b37af8cab2c53233a6e363e153966e10d6c7606a23a51b9358bb964f49ea3f19af1c038c5a1dba87b68b5802fc75f8c68a5486479391e54e743ffb64c185286140db15fdaf51aa2c6173fcb3d60f736a460623dc351f035d546f75fa07aa496f65bd8e4a66913e
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 3babb27a2dfe4e88cc8c030cae74839c9dcb5ff5be29776bb3b2dfbb1f52596237ac9188002864684c470a7cee03ce84a85aab0d4dc8eba4513908dc549458d4f979c0e057063e879a5bc6a1dd8959f45d9d2c1fcf156169d351d038cd0246990d19954b04a24bcba380e52a38b2cbb9d5b9db1af3ac0df31a458bdf4a9e1bf6812b9c2469a8e384a96d1ba29bf009b8bd0bcb098f55523ff8e220ff2aadb50cfcc2eb927e9357b51c5001123a46016c47bb7a8ade6c62b5cae190a3c89b7993d130e279f0571643f039940c5e0e6c212f39bc20d014217ee8065090eb249237873bb3d05a2ce846d58134a4ef435eed617e4435e044471f86686db1572d6531
+Msg = 587e0c53dc96138e7a0d05f8bb10e6d7d8cac64a87e538e7154e06a2b53923f01866e12d3da2643b8b90576d1da9dda35d82cbb6d44d141640a385b1e781b2172c9030dc60a9043eda985c084a207db74a40fdda36b532bf3ec0ea4bb9295c2abc845f29ecb3dadf90ac7c93eb7dad5ac88dc48056247a29362d9e38d33b0b70
+S = 40f0315cfa6e8180e68c9f409917bf35f6feee875faaca6f63d41caf57ba81f1994e4781bea5476f58feae8681229546e0b0ad4f6965e08b8c4b5915a7ae72430c18e556c9ccabf9b2adc9f4a188bed3b70982ff3561290e90cee779fe0c0a98da503f700815b9720126b1c6764103df4e05aeb81adcd11792e38ff4f072b5f403e458459e2e40e453bafe96773c489a3b55ce8f3a2dac7b5fcfbcbae53d6b27fa9acce6c3d9da72c355e11e8f56290f75fb53bd41bd0fb822662d218c6e6b8148c5a058bc2a8855e00d7d432db7ec3207be1f106cd1497a55c46607989fc295426b2f06bd7bc4da7ed40604efff01f037450abc3a1e0a657793e782f8a2389d
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d060960864801650304020305000440f7868e28e7d36a3691e196c831ce747400ae162cc2850af22ee47105eda53fe7b8826b1599e66035a13e247406b04b27b4336859fa666279991b18ae997466c0
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+n = 93397894e668653afab24bf55c15071960a81157e680444891c42ac0cebf9ff99e3739e12d0223d62ea048e77ee284582a707050fd11258f27fb6a4e2b583ab37ed0799708e3379e41b191092b2f4631c974dfe81993c740f21bbd0d828ad398893aa33101f445e5ff02ca498b8a851100e8d50aa2fe4c88ee38be966222657f943f9bed73f018a4fd371d208c362cb2aa4d1cec9c68f8416ef00ded34f4a1ee4d59a8ff4c5b3deb33c504542dfbd772ac649c8313644a32205a602cb5581819e4f4a2b8150e63e20669690429a4b5cc77577295183ff6b760a1b5fb989f158107860751c7808c54c1c511d3057b5e9537e009576b723dc9073c0b03f28955e7
+
+p = cd819c9501262da3cf149709f0f56e59c2783263e399819dff248ac9e674c5d1e281e2f6471aff294b6e1db918d1d52f20bd4777b1175440c9b40da42b1c6a0cb28e404ee6446d19cdf7559304a693400d94e826eb90772fec7835cec7009be5e6b09ee7052d0b8ed413eec628d4ba9ea2dba3e53fb6fb7491eb3ce3bb16e88d
+
+q = b765ec141594c3a8503df7bd3e31264a88bf76ada5d529ef0969724a991787e8630cf8ee8c223fb9894c98679235139a5424e778e72309f7ff60fd5766d3edf0aa21f82d13c1ccd9d75d7799917b7abaf05c1f2dac240dd0bf3c1af0d1f5600bf46e93da91bb36a7031436e305b427af5a090b484a2c0a397d89f92c5d9c9d43
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 16ae604b3a4e9c7f1d616e2deab96b6207705b9a8f87468503cdd20a3c02cc8da43d046da68b5ed163d926a5a714a4df1b8ef007bca408f68b9e20de86d6398ad81df5e74d5aaac40874b5d6787211ff88e128cf1676e84ca7f51aee5951efee1915dcc11502a8df74fac4c8451dda49b631a8fb87470f0ebe9b67449bbd1640
+S = 3a0751f873595e6c75cfe668304ce23e37da8f2412bef538256db7333562cd7b7457506912e176b8af543d5e01eb9742c8a42d356453a9d2ea9b78d6774144e3237e8fb3c0822c16a5550cc8dfb52af497df73d30643b4a8abe07c8e04cb165909e030faffa2429089ab6ca3d88584a0669e4955334ad5c7d41bc5efcb901f7cafe0e31552da57833d595fcf955247545cd057781d58f27c9c1a835f19f40deed90628de42de3b3efa4ad1a7311e67ee3354f6234e7aace3d39751a84611ff53d3ba70a552a78c74094c84cd401eab240aa33bf9c1492d1e173750f7505966ce83fcaae886102cd139f827386ff3898e7a1fcdde095cd96165a11b47ad5a43ca
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a050004140010617ed97007b337d2736ef686b8bc4f438f2c
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = b3d09ef22d893ef3cc09eaa9b2777e982a84341ceaa00d45956f73e484761ce6c61b31e165ccb0edeb7e0fb5255922ce27b13e4790399f8110730740276ba8032fa544919c5493d583cce5eb593a087bfe936c46f9ca85fe0646715bce93db6bf5581f2a5989ae5299ddb574d583f948b5110542adbd88657fcff95c01567cc7
+S = 859c4b66e9843f82baf341875b80215e16acedea013b10511a993b8407d72bd5dd00589d4016dde5b082f8cb0fee5f339d3e4167ba2399269e215afca6ec2c1ec3d572e214f9513086d281a4ccb5890d75bab00eb4bccc44074de6fef0e8c21237f7630557374da6779889016709aec7fe8c2999d14cfdd9a617bf858c941674737cf0723f146759e4aa691f4bad8af3296027f92fbb81476587f76759592cdc389a34d06d2bdab0bc87742e0013a11b571b58cc4990828d374268995b34d7eb8c09928efe0204cc349c83f575ff70ff3d4ffc9026561ce0601f17c8cdc945a59b44d8323a8c3dcded6158e880c7e1a214c2d3554e814a0b9c64f35724261452
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a0500041486b684bc197e2f935d2cbe5ddcc6f94830a4ce21efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = f41491a2448f0abab25b9f4958b6eb93343282e62dae1d2e5485f7c369057685a1230e2ba66c63d8e03fadeff33a612989f20ee551e784bf48b73c633791f4a47ced9ac80e7a6b26bc585cf4b588b95a4da10ccafec44094add106b52fdb78f00cdafc2183a06ccdce0f74fda7883b4d0aa645403d2d98d60e3d1d615ccc4a94
+S = 81007a0eaaab1b6205fb5579a55d50a7d7b4bb077eb0cdad18756b4bddc447cc6f1a427cfa32100cf5c0c00db6d28c371059e6341d947d843722ae8fcd0c81a4650fb96857ca5d09a270cbec62a2fcbf997b67fbae0763a5cc28f526c452b416f25fdca7bbaa82c966e7be2a5b0866da58b05e024439f15428b0815117efb9c08310e193e7e7a5f2371f7c2c2edd17616a7fb991c2e173b7fd80ae4537d38ed647c32dd16129e56600d32418575c608f360368b750faac157a3a43ff665a5ed5c545e07f413e9475e7d79d542356358f0c554cc206c3880406447308d1e0d1871d90a84ee4a43152488acbbeb7bf55fadaf3e8b32e01a363ca8e3935efda1e43
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 7cf8f94a517da2e5f856e8ddec29ab25a1a3b1faaf0eeb193326f92e7228ef8fc02d5a2aa1b67ebd2d88e245b9ba0fb8b30c94f6ce7a4dfd5f11e55d07029aed93f540bb209f8949839783f6e86562bab8dc8016c1aba24b912e7dcb228a79edbdf8b4e418614af2c22cd4d9c0542e9379bd7e42cfc8716a8f25c85e0be814f8
+S = 636d180a954780e947e916eabfcd4cfce80dc0cba1cae58342e142207fee42f3f6655ffb6c78f89fe1d2f31ed54e991d14b814583e8c84723263a22734acadfb5bf00dcd6df8bda4ebb3927a36b13bca2991094f1f92610dcaf953b33a4d1cf571085e297e3cca697e4aec953ab2134e23e62d176ade623e3e2efa562e7e0a87fb7ddc3a169325cd01fee10b2f6ed2012b9c9db99089521d2d15a15da86fcb165501eaf454bb36c8798e0476f59bf2a7d5eb395228744e266198032de0afe58cb10f81dadf57dfad47f764721e54f1248c00f98d7fd2fbbc5aa0998b8a480a73df7c2eff9940bbf644cc821ffa9bf570f2b24c43570b81c103cb4d0c39deb507
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 7ff7ba5d5e8aa7de3ffc560672a9c1b0f2eee1c39a8d7fb89553475617f81ec04a46b5b28c7d5e08d7f71f80800805c02528bb9be1545b90c1b184937c73ad115efdb92e8649cb51518b5be216118a52146eb25ca8d7428bc4cdc9fd9cfd5066a264ed57b5b695c1950132b59b8df56da708ee9059dfdab284ef3c1adf5dafc9
+S = 55fd6153dfbdd9850218c3b48a4f5e74e9aea999b7e0bf0514481f29b9491d62a4a4dbae2fbaea27cd4dea5ddfc17052d3598bc329eb3ec437d1001387510d7d0288cfe298cc5fd9f7b91c887d41d81d6685853285d67e874467c036d52be31ee49bfcaaee129a3cda168b59ffe523ef64f7e972cbda2afedf1a0fe7c6d457d79d9a73b7424fe6ec4290988dd81daa58e1fed69ddec52f8482a27da34b70114cd07f04591c5d2a38eefba0abd33d4c1f500a4073eafc5199548d7b96c772cac71cc02e18fa998f143132bcfa5e44f2dd62692c90e9a96b243ee20310fa9fff790b04a2d8811b46c5c97e66dbd5e36b03aa290cb9ae27ba94018e61430eac223f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 3b9ffc79b59b069fb97124a6c13d51ad413638c1e8e09dab2383f90be4db64aba111b80d9feaf446703fde0fbbaded1a3b8d65a20a26c44620225d17163f43f0304768069b4206bff3ea3ec8095f0062e21c2afc032af407eb938b06e21afce4f129548b320b05b24a5b8cf633bd512d3fcccff75953f4958ebfcbffcdd45830
+S = 7f2efdaf79621804a71b9fda74328b00a65d949b26f739e1b9755ac860c5ad7bf63453a572fc54d6ec790230ac91a150ec428c252f2f8e222625b3e3e65e5abe5155b55da30fc2a89e22101f15a841058ccadfcaddb5405738d86fbbc85d82062dc988a945fb2afb9a9c4d52494f0cfad39f120577931632c31a63f06a370d1150aa4a45441bb31ccab8f7f742f5419a14a302ee0c558de496c66002a02266154ddf2b5808e33b920493e5db1719c9e6f7f43a069455024364988ad622d8d61a5b798a5f9849cf29a0d59eff8459ca65dfd0ea1a9381e8f595ff72d59bd86eb04afe1c4b61c239a746eb102effa940c011321dec7675d99ec4d03261ac254602
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 16ae604b3a4e9c7f1d616e2deab96b6207705b9a8f87468503cdd20a3c02cc8da43d046da68b5ed163d926a5a714a4df1b8ef007bca408f68b9e20de86d6398ad81df5e74d5aaac40874b5d6787211ff88e128cf1676e84ca7f51aee5951efee1915dcc11502a8df74fac4c8451dda49b631a8fb87470f0ebe9b67449bbd1640
+S = 13c5d85a48e10871542ca7b6c7f7fcc0f86da6e9cca9fb9b8f36f30fdf2f320b61b73ca1ef0b9c07af8e675f32b7a648ca109885c006971e821f09a489d1f8b79dd2d03a20b5d9c02f0117bba86ce8b419c67b90093d89f2631dbd38387a847b9490ebbfd7b6818f70e09c3ac25223ce2199030df51bb5da8242d1dd2396c72062a60f481c73a830c109e74b9fad92d7a9a414643ccb2e392afd13a8deab2b4433b0ff5eb3c01892c71a00a3e2d1173506b6340f57ad27e54a4bc5e16d50de2ed519f300f2afff9bc2a39e42c70a0fb02123db01500bb79dceda3a33b915ba095fc1269542832386a19b3ef65f56d8bf64ee4c83d5411bd0b6f097a749556917
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c35674247cb0e952ef2d28bf3e3c63c34d0ea8b3f194941d3678440aa
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = a9db46f44d85c4414d15a62541906e6ae498c06e2336191174d6bdd16993f13485b56b674e780724a310bbd850e9cd06e03343e6b39e9c535062bde4fb832e588b538637763824b62eaf20dbb09181e35996b1e1fc172ea7331881e9f28574a062bc80adec4c85bf93fcbe768810f3c9f8c7f0a5292837d6c5fef22b76222bd5
+S = 0ac7106eefb290dc2681c447fae564aad0e73028927907b323a7e1c340efa53638349d3ff6f9bd393431f085c84bd5a447a82ac98cbe6100eca7becaefb20fcbdf3c13cf883538e39a7c47c92e0a0da716bf520835156c02ad30d357115e467f9fa1b869ed1e6e1736402c2df62276cc766a0916ccebd7854f0b6f14e88de01164491ca82ed831e6e2f45b636b4ac73a3a0e0522cb47ba1758dce66ffe9e6afcd09ee6820bea67ff7351a157aade87d7243e68d3a14824b07c0a831260fd4b21020ad943ab0aceabf2fd259a038d30f786ce3a60c6fa68a5d7b1901380b19912a7eb61da8a224b9f0d2109bd161de1d3892d1001cdda4fec492bfd1fb0050039
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c062e999e48e75ccabd60ec5e67bdede1b8beb5c89c5b8455d638b0f5efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 659bd5f2edf90ba229a140bceb69036750477ef4f4ba4a646565882ad8fd2d321b669d21cb197cdfc7c9c053e4460b6de3a1396aa09134538b1510c75c5b54fb03e195ffdeda4a432fd3db59cd96fbfc1a4f385234edd06e70cbc719049036d20354e6138f041dd64a07b8580d217a1ddd98a4341a96c6bcfacfd4a736637cbe
+S = 8742d7f61cd01a1cda403f08a9f367dd2f62895531634920eba3de112e3e5dc30752533851ffdba2bb48905d3532e2a55572ddeeade4dea7f80664b243f951282ca678194d6b91a9fdbaee763b01823ca4037d77cb3aef976a90bcaf195431b3856c3b598bd2c0e9000970e49d0938b3492b6c710ee898fc719b40d0b5cd98a54de06cea29584361317f4d8adcb23b982479513289c4729ad5b39fedb2ba6a6cb83fff0c2dc35d8997b9bc0d8bbe45857ffe3da67655cffac7c89e33257bb08ce3d10610b53cde7d8b31d721ea34fde8f798cf91a866bc0a52a9aa03e24454e0ab27f7cc00219072b3cebd9883ed1fe5dd02d4b59536488931d5c6059794da49
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 25c6f8cff7a49f5c0b7c1f02e3d4b8935c26cd768f33e79dfa9bfdb6dbabf3a6dd766033f62794009095dabfe718faa2b29c021205f346a47670a6497fb10fc523bc4562d44edfe5956f93c15c4ab38bba3cf8aebd2b7f60161911d477f8a7b13fc02dc459c087f16131d2700911ec36bc2f36b0818298b721bec6c18c29c254
+S = 44e33dc3011088c96cf066e4a3b93487d86779cc770c43e7a7b5d6b722cd582ce8988a28605a4961645d9bfcf60b68a83d8a5f2a85dd07f358715fdcabcea43c2816ac12771e76e54c14fe3073e1eb43312cd0e2fa0c93f07b0c215220c59379121aba72fc7e13702d9152386f6554b12b0323cb42d09ac5ad5f065fe6b045e37812a55cc6132a6a9dce1a7928a974e3e35213719b3175f96ef87dfb1cb84a67bcdd5f5b15fe2508bb6815809404e0e6b1d88da4d7202feffbfbd76010279fcd4f6fc233b27a934601c4e3701fd00eab581fde1d2aee3e27ae9b7b627e208d013fd0590c3718731c19f105258acdfd10fc8c542982e6d86b7c275372b8112fc4
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = cdb5d9071fa3a040095d41253a6a8081200ed6f4aa095b455181eaf9593c7f255412e380e9a28cbcd345be172c40f72dec3e8a10adfd8a9ab147e9022524e1aea74e934807e5ef144a64d381f5d477fe883f080e4868939f41b925988c7d31b1ce4f318701d290f077a3c88b1b8cc89cfbfb981703b23ffb0bbfe5e115af35d5
+S = 1dd48357b45763f1bea1c5a7b0f346ca8aa1ab19b163e05c78128e5f9625a22a7b3b1d8c18763349089725fe41f7431bcd42b965ae6f7dd00ae046f7fd2161d344b471dee5ff1d9fd4d5c520a6facc3bfbd8650598b34ea6c94d684b0187a2437c529e4d6408852662fe70c807c1270427b02db59f04b8df01a087f3ea9e3c80894763de195fe7f92dea8c70a3bb85864e410a4e8313a836e47fcf5050090742fbb1eb64703d5d599fab43930bf4b8a916c134f4984993e2723c4a5814265c500da5caf709143899c5a5d8eb199479aa0cf68366b7e80ff21d1352bd2bac2bb2c63a8235a379b3fb3baaa416243eed20c2c861e4924b71de1a74bfc96a85ad74
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 14690026e93115e009238306861b8968408c9f320614b61afe54c1de47fe74eedc2f4c65bc00cf3e485815c5ec04874b0109e71ef23891b99e040037fe91930e080d91f9d3436c36fb6d42f2474aa9028971acd3c6e511a497e9def2cf161b345eaad8c97623722fec0d1375e01878f3a06df738ca42c044b1ac63f802b592ca
+S = 0356405c184af63e2f550081e8dd7dc7138bdcbc44d22e6225bb4babec42983f0556989ebb8bd6df4fda3b1a3d4abf2659a584ec0790379c74c7bf156d14531939aaf920fb9959d5e7cd0d2fa4f86c8029e6271522faf29499d50bfdf1b20e68de2fe4a52a84db86a39491e0e599935c3b726f6b7b876e8bbc633d05ccbb3aecbb9d1e419bd2bde528f6a7ca6ab4c9f8638a67d9aeef1491af6c5fb1c29f76a68e981bccad09d3eccdbb2fe5d44a9bb23a10f9a0fd594173b126fcf145ac2a3420e78b6b195ca4630aa2a48fd62192f21c34e8885187489eef8c79a67aa079fd8d2811a5d41b73a1cf78133424943b3414dd183d8ad242158e3c3c956185a153
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 266a05f02ee6137da278d709b7504bf55978e432c215c5aa4cea34db831d4ac57f3eee07718504457b5be1ccc51c0279cd1cfed7fee8ba8785cedce5609f82e8b7b3334a702e16e9fe82616e7935152cf4e5e94b0b898325bbf9eef077b1499e77d1bc015469b133d2f44035fc22ead677db8bd610808a4c97745345f0db07ae
+S = 598ea4dc537da91b6e9593fcb39d89f28fbda380f1b42858666b6569d40688929ced67f6df07eb58bd984fcf51a72b863649603b6e3be9f99cae28015959ba7d64fa4c0f188f849774760074d46131a5b78b712d50266feb110ab034b62bd67b38bff88eb5f04cc174c8c9e2d8f8daf6c33038a1a10088698fa09b6c397db2da169468fbe2eed851ae1265cfc05f19642d8d6ada114f4ff065e6b7b132d3cc498ed23ed4317a3d0f5c5462c9afd7dd196faede84f5f8e40b3bc8913797f1e23ebb3aebcfb23749207c95685ecf0e3f164291c1fc9087a49c88fca0b4736c7c86fe1a159b6b34dfd30cc626ef4c458f712f4a879a730e8fd6b2e075cd02b96011
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 58718b3ba6a4ddcaa7d3f7bd46cbca5591f95d87741fb852c74b004f8c0ae38a71d937909ddcddc9a8d3ec08eb490b61fb0e1f3b70e827a5eb8663ee57b5bc6f6ed760ac7f90ad9c6fc25044ffbcae8b4cae83499c60c8a15724db91540adac756524fb6d72713ea048a6c98088c797a8dc0d0d980f065ec150fae600c6f0438
+S = 29c5a0ab72d0219034ce32ed330a4b388573eb804713d98029fbc1da87a474eca1f1814dd61e26c7bed630f3a4f980734321d56fb3309c751953a4dd9110c293730829bfdc83cabf619b220818e30151c38e6bb9d304eb7204029f8af86209275b1b5fb84bdb12aeaf3013db78d6dc1bcbc23fbe3dd7eb3c3bec332c8453de3ddd2e39cadf7e062f00a682bf18ab68ed3c6bddaa9dada51c99117eceaf6f8179eb9a59e6143a56d5f26d4138a5c31e49104c5982cb1b202253a292786cdb94a2b383c9d96afaf83d52160eccbc42cf2568744999a662097b315ded7fb417a823e3e9b6c5f7a822bd58a4e5542fbdfba63f60266c0b86a363153ae0444e0ee1a5
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 35524c5781983f729374b6342099239157485a64b9cffd112b50386849c3afcdfe3eb5965174bfb5827d189756d5d64cafa60ce75f4a41283e0b21587b2e73752f314b8f38508172444e61852c71a4f284cfa00770c8bbddb8d425371f7fc7acf1b17609dc336df1006ffac6497777cdfd497c8c91525377c130accce0bc92bc
+S = 77fa540194591f2d49a7740936cc5c909e73e970fc833bd8031dbcfcf78599095bc8d185cdf681c4855c4e4527a75c5552ab3611fa7788c424c3b051d1236fb1bc3e7b65421cbb1982ae623fbd65210035c78032476df3d64c8e8136c74c47b694a881479608568368fae8d7374d32173240e55e074e4a064f6309df823269f2a2477a5bd06c819b67d9c5f0a8720af431c3edcc85a1b2cac7d2288d90b446b62cb070d1cbb87234ec41c55b89318bd852aeb60779246ffd84532d08ea27e27347c7997e7007da4680f4b7872ab89499a1b0381c4837893fd0ca055bf1f0fc4b1682044190d40e7cd4b6c077faa077d27cf5a9966e95d6acd89f1dd1a61a8a4a
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420b7cc7185c6cff2f0237380831075de8079252edb588ab3a492e600abe24dbb7eefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 31dce7cc7c03a063b9879e0343e9b6461db1992333a941bfe34a8f86bc74327b8662cacc82dc4daaf3aeaa57dc5aad810c0a23ce58c83eb828f13b9b35e7410c90078d6de7dbccbe0490c8b696aa471334f6302e9fc0f0d247471c4e116e58c958b477d63266e449f4144048f8414ca59d5e0a6b90fa1fb64a337cc8da703d5a
+S = 8be14c18fba2b95cd0d0fed4b171462b07db0b5e5edf5803b595182e97ac814eb929be28d18a8f45f837ce537475fab819244788681676ef73930ac28062082b6a593072b2218862a80439a1b9e2c637ef9806463c7c3120a01473ffd9df2152d871b83d782baf6512af6979ba3a9b8d68828716539c771161b81bdd056f7535e2cc654489c90ee5c1366609c775c760cac8d084ee6d618d25a70ef64fa631c0c4caea75296d97237da8c977e711374620f232e71163d2a2515d71e30985f84a3d4839f4367a2d273f0477bc677dc830302ac423364f4628d7cba5b92d5c9f37de4268f8d957905072f2cbb7249dad4f55909e41e4edce618535c7cf62001f52
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d0609608648016503040201050004207f3ac72d5591ed16096abd35813dc29dfaa0b834e2b57e45315b3731b4d7292f
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 2656ef08c07fc1ec469aa9c73b677af225a9f5f6f8d0e150d1d65e71e6677609bd44f5859de97ad6436ecf75d5ab76a41c9f84f6ed13b311e87ab2b3661cbff3ac7378ca65d5eed14f54fc4c34e3d7681cbae5c1c1fbd3274395e2a21d6881b358ab21ddfe8b4564d215d8553e56c4c68dc1c05f5ad1691a48ef9546f495e4d2
+S = 849d23a7f9dfd0956315dc9a60c04dac1d7db660c67d2ea57db40098a84d258b111457686821134dcde66990015e769311aa53e1920bacbf59d214beb3fb79cd6482601f5ac3848f90ebe864428d0854a245c1a51f40b10899cc08fc4dcaa6b322fbedaa7b56db804009a0829fea827065ff655c1f82497c5d59998c8a577bd5e170b4734b7a24f574db4ac56fd7cf96039c594e9a109c10185e69102e27105533d826d50b5c39bd964d88ccd2e0a467a668ce15a84014c958723ce6c09230bcfdded9839ef40bb5f80ec2073081e5e6565454270937b8cff537c0b065a923d173ad04a31592fe699e2424d8bf6bb0b947ff161a33b9b03fd69892a0d9a8c711
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 1c58bd7408d1d2ecbab294bd48408178d4a95be7ca3c89e963d8bb7c6ea5cd1c4f03ee4c48c00172f78e43e720b42e4fad039e26f30c339c3790f6a371383f464f86d63c7d0c58bd24dcdc94b13fd776d7aa3d92d7ede969ffae3fe07016109325cabd6d311da0764884a7eb814a42945a848052fd4875f8c21ade5bf4a708ad
+S = 60dfbc77059709311bfa31a69dc9db4703d0fc44d715598afc39331e2620d73423f2cb8026c3dd9a133a7c0a62174448128934c776616f1f9bf12c3936f52340d4f034725a759cda95a743602805f0fd7bb03a8d6fba9947d1692f6e7615ae3b89f4251542f5c902f41661f443101da8a666654c86d3cd8aa93733d677d6c4e83b527def0db12bdad93feb76e9bf986a1624834de5febd2b0a970db189c878bd99d3ae86decfd0842735361bfb1fb0cf548a9bd43411b4be4b8db8db1a585555d9fc5066bbdc081ade816777cbd29723062ca7709429331bb52a2e5967948d1d6aafe979a9e12cbd20a30937bd6965d1a04e3060f72a46fd3af1127dac637a24
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 47611125ef346ddab85ba9493e92eb1566bad85e9d17f99664bb63900b4297dabcc0a74dbcf89ae2eecf12c899002cb36a10a876bd854ad418537f93f89744d3d187449e50a940c0e344b4d97b15b8b0914224ca6794f73c90e0fabdb2c6a0ff8b9e314032b0271c9fa3d9a56e3956b5e039948323acca75d34b1a35c0397307
+S = 2fa1aed1f8b9656c8216c2ea8ba98c67a6d52cc143816c7f83b5f72e572d6953c28249593bb01332ede6b991ada2ea1004e594966f1aeb2fff14db6ae311bdcf439c8c949de248d7870b0f9f3edfa11705de95b552d3a0bd86fb52476981df2cde1df65de3ad7b957fd82b7f98d8c6bbd4b7e2b65e143c627f5e4d2cb871326ced2f904947ec2250c5ff9d330a74a480afd38277909d4d040781947302ebfa6ecd229d93b5261eeb237dc99b9060749bfeb189f99e0164ce36cb0b64935e52870fdc8cef93a0e198465f48d7ffd87c9bd1b40a127f0fca14d559ceecade77d30486cab930ba50a3358269f641ca11ccb30d3fd21becdb50efb778eb10d424b76
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = af84a31d1c08faade967cbb5a016837fb2d1c0bc5eea5b75d4e2a6449b36f2c3307b5545f0adaac437c5d81bca89587572a8f106ea06c6f9fb5593a9e6e5341302bd678ca6ead2af4917489ae85e485aa95ec6a3bd8e2ec48ad0a7db0a4a95456e71615908667c566786a199c43d5b149d1ac8fb9f299cc0c97d6842cf0c1d42
+S = 014773de1e3486a2d54c7a0a0a1a70caf61ce94868902314462c2bfd9c640de7b499578230a41734a1822cd0fde610c487c1dad10e35d70136cb162d79c403c7408cba33b72fcafbee2dffad251ecb6bd4b082aa5350b194c587b8bb1ededc902df1e2e6eb03a5744c87ee49e087759237ea133c8484d62cf142344b56cf3c5e1f72998c531129f66e0458bfd4e8b1de1866e76e3912f680bbf8a96ee4f2971e6fcf029788e0dd586db744a7f9a0010a2a27d98b3b04884cf269f19f1937e8612cfc5b144b7aaf9b2fb0464a26f4013de9fd12851c3f8c9bf1fe6926fe512e0543114cbf9bd86336d7d2aa6c2a696a3fd071467784c2cd8f64e8bcb00fcbc792
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d0609608648016503040202050004300c4887ee786dff1356756432824889c71e522ca5d478d9cba311b11a51dae49696d1f1f454ce4017e74d9f45cb17b797
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 5c95cabba94825969c306fef29fdeb104955f9e7fdc63aa29000f57d1d41b9d85210448d732ea480a2ca9c785df4492d485405a22d1c8cb4413b5ef3a9d464b23ceed55a8b6d5b041e41724601dd114c80ea8d2b2e3dba732c075303a74c9c22a39745cbf7eb924799fcb9021c9f8c977780572d08130c06d9cd9d552193aa50
+S = 019962ad704a78fce2306273ff3a649fe973dcf2dcd6d0e692a592f357c9ac459a15b0bb0ff986f104f99301c87579a321b0d4ab9e947a9de47b56c0094e4ffa6a8949594348e342f8eda30e68f5005bbf72cef70c522a124eeab1d7441cd65dff7e1ad36bca0534c09c284e8e931766406b43b62db89472c2514c3d1a6911a92e19a0dc923919daeaeec53746f487e06afedfcb679b531ede784d9d6072dad50348e1d8f01094f29cf5cc96f6c1f40ab455be6c98788e9d7615ddb6a66b893913ad0cc63a72b9dd357ce086b2df7c8a106c0c363e3e2317e37815df69b22a9d52d6e5e47d8be17ba61b2b2019a0f85fae30e1d4f2622be50086848cb405d578
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 7f88a5d6178889bcf09ab7407a01bad132cfa7456ca0fc294f88ce56214a24c5c5cb9ea581c65aaa05c017a7a93f9b5ff737539969c53a72731ffbf7c4cc5af3ca10d00674ab75f73bc3244b631ed9177e945d1233c426ee3d0778e9b6a2d19f96408422779fa44c9b8923542f063ba0d1d00dda51078946b4268d537f365170
+S = 91584aee68fc0d4e7d24afcf4eade5fea0ffedc4d49d1d75e673029bb998ad170ee5d1d28a2779c846e617b8c9783119f4af4602461434a24c1351f737ae315868a78f615019234606a12e3fdc3cbb05d2f0cfc877b344fbecec5f71f0202b507df23e4a3917cdfbd1691fc69c509598e2bd7c71ac39a71a295ae0ed1531b97dbc6666ecdb830917f04cae848f8b18b8abf191091b07632e1632ff611432b7a50c0a7654d59506ac3b4c058eb16bb66174a39f933a4c389cc86c9c124a3246402928a3e3fcc8d35a817027c2c2448b792f2009548516642d75839b61c6e2d5b63c4ee4c0cd72e559be3cf0e466a4a566681b66b71089f67c1044157d78215e0f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 97e7bb62b6d35c8e423a4c98de8264c14eacb2b12f36cc76e54064cad6ef1d94d60f9db2e1fce4f610c2dc6ec68331e92a1962b6dbfd19afdf67b877dcb734ff8a14264f68531f83ae1a3c138345fb5871884d4c1656ed921c02efb66b259cb59c3f7dc0b1a1b63d048a960f7e906b1709419bfa480bf0258559340febfffebe
+S = 6010444309201677f71890ce09e31f671208b2804c309a85a401b275eeb5d234ffe5fc6dad17fd9781cb00ccccd1d1260c2d7090652add1b635633170ef5e9eec6ab240c382a3850fe0947892870d0424bfbedd434db4084ba29cbe7c8a27b4aa858b648fb0c7096db4dfbaed09fbd7483a2e9d8c409f87c9a2a26984137000cbe451140da9bc56c4382a091bcb171c3da5f9833fd224a429353439469a39033f2e1ea20283c643eec651952ac9853ac15a8a8751ce72a443b41e17e41fb86e69ec0620660f65361035441700652619c9248b2ebe5cd83c00bd2b232c13b544b470334d7314704dde6c81150e54e9ce132a5aaa3ac03a931113160e93814e968
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d0609608648016503040202050004307c1b2374e40835303155d969bca1d02f901e2569823d83b1b8ef0221cf4af285fb3535d60dcafc85b0b856d7bb9229a5efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = f167b1c5e4e480c6d96035630415b83c9b2d137a2ecd6efa37523eaff2dbb9416e078dfae400d1e349b83c2a1f7295c790856a5fbd5c056954c29c8f605cc85766773802ad05a7b5dde10bd6cc5b10b994f0c47ce959942fa9c87738b56e69f600401ba5e5fbe982be650c2fb2d61158cef8899757cb03955fec377397168468
+S = 6e2cef82eca498f7f1bb521fca7f11b31f1e80f5d1face48609d78b2ba79b8e82c6800e92d419c4c48b7bdbc6c41cc2b9fcbd05627c1f4c567629929022baa4ea1b431f361b08afedec6eff545b682b8d9a6b18bf62f34a1596048f5455f51d5496c89eec6e7f8431ee271ae84658347df2d1a52a5acc37b0b5eb1438342da02f2dfe44e50877221a8623b1d1602339223748df48cea785f94c5ee719e95ebb2ab7d795dbf53d4055be0591e203c6ef69d6b08aff07be7e546f501e42c3192115b5f2c259c4ab2dc585cf37dd3ff54e89f0607c5e3a2f198e2875a7550bdffd0eaecb44adad438b3d0ea810668eabb123baa66843d1a136b0369332bf74d91ba
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = e946af251dd8b043a9c866cb4f5e4b65e5a983b4587203e4f16ef982d7b76891d67d13da5ef99d83cfa3eee3f3a5d995cc8ffbcb914ce6e5f3557f43a424a4571aec12fe918786104fb023352b7214fb50e072263f07684813219591090cb1e73ffa7439bc69b311b156cd69fead45c0f805b06d6a8ad232da3a04140d55d86a
+S = 839d586ce12b7c22bc2e0d921d11756a9a65e8275f61307b1bf1d6e350ac126a50c52363f561e2d2f8edf3f92b9fd88af138178ee34fdc3f4d288bb142dae2e5378c50754da25eb541dd80e83f63a356c760e8efa03f07efc420109bae6c701fad5b8dc8fb266e2ce1cfa7b71f04f63c692e4b0aece6b970baa77914791e8a25e5100a2205811da238a451f5a100355b28abd39964d43dc0e2b51a8e2ddba0e94d02ef11a5cb2058acf3f98dfeb34cf939b5bb0525eebb17bb25e517fe3eb3e04e04afa892f318618cb66de38503bcf994c9d2ec20effa04d68a0df7c76dddf30e88e1fdf5afdcb2dca0e124946e7f39248633b03166027611deb276bcf2c0ed
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = c41b35fc1669b8663a14b3c37c87f27c2d1b7a539b3b1da341c74be93ab52b84fcfeeab942b854fa4a7fa168411a9196fc5cbb90e847211c4478093f8dbf08033a0d6078aa938cf95b2818b05cebb65d052a8f52e583d7c2fc49a43c2a2a0073e80e3c40364188ead4d5c1a4b5428a57b1509ea27a376520d104c5e9fa3e3a5b
+S = 2ce448ee7ebf21be380247cc3f8472e440f3911128025fef0adaac37d4dc977bc5f81224dde9df193907c17fbd624ddb51c2b54c214af57520d3f69d12885e3b47cb2c005c18eac82b86d5d514cefc99794badd609cd5cb8775cf685ec1ddf6acc0272a4a58311c348381bc24c4b85626993a601ae292b13c3e8a9c0262fb8deac28320810e776c196454be73d5ad08f780ef45dfaf7704435f2b3141ef32c2d7ecb1f26398a0dd8c01c39367987f22600b07979627b391276d1c444ec87e430769fe22ec3e1d5cd4df358314282d10e2a4098b6658ffa44c4135142c2661f2a80d4d380b5ad3d2727d0ce12f1e6d67af797c3480100ea50a0fdb0bd1cb2a78e
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = c069fe30bbe18aed9d39d26f4ebcbd89a9f18f07982822e5795372bfc7176089f623af809ec15360dcaaebd8f61f8c3b3d35c0783871ce4cfe943cb6e4b893ac589c620c0d3d85d559a6a797db080628600d7699076aa968a4b4adf76374b63dae7d1ebc507daab3dad30f9445a0b5b8da21ba524f3c3aa23358ce6b8c7252a6
+S = 5e67fa94c7e19b66548220ef4e07769ff75d4e76917004492334f0fa15ffb8b14271301c170e3d325811bdfc1dc53f1b4369a2c0a99d261d9de59a73efd4ecedade05da9faccaf35d462057bb8bbbe29e3f5d4c383908c0b25006f779399064889441a84e0ce569eb474ddfb83cda6be253743693bbd551f6ac0b8cfad225d5635972d4e508ae5f7846ee3adb61958ef53146af42d0c6ce32559f661a3c3a14068b8b488f85d7e5641e250bfd9975653ad86f93ba5e5f57f5799ec135d9af7c529e6447ac43b114475060150e98ce86df3f69cabfd5a59158f0f8c4043935e0fee317901baf27aab76a2cc1561d969bb3d69de65885bfec00a522c5010fd2ae1
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = d99885b2fd968ed1385f0245a8ec086dbf33cd903c4a1c205ad0303b4789c677d74876df7a1242396c80708b2b6595dd2eb1f33fd495040e9be8577492ca9b2e1187fa92a7bea8d054c2bb78f8403d3c0c227ff890b4b1ef4405b0571b911f19ed1cb9d26ce1e51d59ec8b14f8c52714c14e1cc158ee4a4abfefe2efcb2579c0
+S = 0efe5b7647f3b6bdc7e9d161afe8591fd21c818276311c4a04a3922e7da47c9ca87bdb8d2d8b8eb267a335ada64db1f19cc35c6b9bdb06589233a834f106db34b75284f943e7426edf57b63d3c23032fcef1cc871530ed003b3a62d994caf8c4c10a90528af67824f5e5267b2eb284c4310706aefe248d3a2d98e922c859be49b71c0278f537fea1586ad9658da5c59ba11b6abaf2433500be32c862796de6aa58fe7955fa51845fb4e304adec80941f70e27ec24f1c6bafe0f2746fa102040f2483ba7e3043469c6138adaf8fe50b4274d9548b30ad0bb048af103454afad3e536c2d95ae24fb2feb08ac0f469551edcb3fa36ca078a469c001d5637cbb1bd4
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d06096086480165030402030500044065183a0ec842001ad183a8b55e9118f29757c477ffd30f57dce02a218238e0a400d6a509c69a74dd64b400c809026e9e3ad8930f550b594be664491b5732f3afefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = ae898f661a8614a533fbbae90eb5e9810ca4a205b9327845f4d3dc7f51de9ed5bb9bb1fd5e9d2f3bc4529c8c3dd86f248512ce1ba1fc9a640a3babfe0df95d6e72ef4b6c5cc35add7095fa0139d5a8eecb57b73da7a95103dfa4b9037b41d2211aaee51adda19f7380ed59afca539dc5289ae5d195e1a50abc358cf4615f07d7
+S = 0ffd86aabb2861142ad2833b1b74cbffd660755d58081f816f28639bd6cd70b6d312d6722f14e4d608b154891eee96ffab837e472286c528086fb323ade633cf1b778427b504701bca01c1a8cb18547cdc3af6afd180a65042c072c741525346be008dd2dddb53d63dc7b33458bc59fd50b35bdc291a2760ac545c4fd21a37b710050fcff970271ab9ef51fc5953fad7bbd28e9d4f84d27c36711afb3ef2e21d55a3f5cb028667c10b23a334ed7e7275b6830588f4938f2c3b9ff795029c5c9eb3965bcd784ed3bb5a119d165db4ed808d388423059ffb091fcdbb1e6e5c65291b1e5fea5bd17e2c5f16be05c3d13bc8249b7f98720b300479b0a25d680cf3f0
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d0609608648016503040203050004406c4c610edabaa9eebb437d9c62286c4f159bb471247b77f443153bea722f2a86de52a83f4c9561ae581f8b3568bf9977ad8696ca8f310ccecd598238b3edf845
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 18899418d11166347f1db7538f58d6843ac6ad8ea66ab60c184b5c7577ca9aa99a5e89a587805b4e5d1ab6d13fd06b640712bd62d4d830ed315491b7b1e409c89522beee817b33efb59d982c31dd365da1937aa6aeedf68ad3049f82406c78996c3470882afe0ba6552b21b6ec97162d8026ce2c707fb76c27b41fc3bb05bb95028eade0ba33868ecfa617b98f829957ba83934f2dd4621e111058241e3c0e08abf7222f142faa81652c625deb28d2718940679869dc51fee3e0e38830914aaf6c0b670a04815c5265836f4e9895c6a2e99111e0156c92f3c8d23b89fff18442876678c2b2c40c5a7c6f7cb1a3d314b689d48f06faed34047ea1237df9a3a2af
+Msg = 0c84d0c19e69926823ae89727d7dc8f27e2dd6a8fe0c60dd2b5c2a8f219b4bcebb089a66a86264bec1f3600099cde47a56545845c0fcec24985486ae2b44feb027928ecdacab8467a6a13ac35b7048674085f8c71181fb21203a5aa6ee02afdaf82d943dd3cd5c2b7bc00101e9ed5e81e3ca9e781822f59d6c158ebd9160c415
+S = 5af917efcb50475ef7d9b555885d07cb1f38149cd8f0102760298131cb6737f5d085f2762682f98c5e5e9918d9ab5ee4eb6e94989bff59af8ea042d0225d71690bbb770ffebc0610afccadb9726c9fba0ad7c716a0712fc4ac4e14ae7c21adca56d7349e68440b3244ac4afae225e7d70b68b4bc80fa9ca6a0b5665ffd831acd05403d8050c35d95caee2d6ad1eb53523a531e87efcae11cd225a102578f8ba6fb4b907f22b9515eba4449e145b9301619d5445723537c16b8543f524f37301989026d0b4829dbc5386fff11b74e54be9f8203f2a2cb16a2181f1a8767f1f161f650f7559da91578b999a34a2eab985aa96231b7200ccc6f38c2a621ab6b190d
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+[mod = 3072]
+
+n = f33d3234f13272c3b2b6821ce4805663ff2e8b0d2a47de363d97fc9cc879cc6b40f9e53aea695dc538a0d2b558498829aac327eacbcd889e172b34f90745c5d528b7e82605f1a58fd228ec7fd4b6f476f393864f48dc47097c8a780a2ecc02f748138dbd7df99c52d822a2e5154c6047fb0eeb4f49da38edcae3c32d3fde435f291f96cad1e09e1030ad7efb4944b69e074d0d7964becb3cb86238d8d293bef3030d141d14868bc21fa133e9de1115f749991cf86ef506e663ac162b2c8567ff131a6b467a6f564d6c588860becbd88970354198ecdd4f1f4baee8f8bdaf7255835385f5673625f113550b123628a0be3994d91c3a19a82e5d73448dabf684ee6794fba7a2b1afbee0287e5a11180c29ce0896795d52ac7f408fe28e8e9116fe0b61a1083f95c5227d62d5537b5040b79e21b3a8e83c225bf3efebb2f808541e97d28a2468359fc60f588e74faad611262064628a25d8d61f9d03d8b21cca515595aaf2343a759b74a6a8afeffca139a389aa281995cd18e16a9cf7b7ff0dddb
+
+p = f3fcc6aae575312778d9e896acfd7c1aa4c5524f20453e8bab255363164afa7124b2425587a077fa0bfaf61b12ef3f0540dc4c9e777122a60610a53d1d75b0a5859c654a8ddfc2ff4860758bf5a6f264bf8bc2baa7551eb7be23bc06978be992fc81d890e07a3abf95d20eee3f6bbbc089985cac96395b473b2741c66bd2ccbef228432f66b906c15b19694dd786c29f06cbc17b2e6400dde4e3db85819382b3d05a4c3009f092d40d05ed5b2e0428a214e15a7aca09b47120b9ea6cb4084fcd
+q = ff36fcdc519fe10c69aa0dde2cf3bc72cf2ce9a54ac063d809b523f4e5d7ddaa5413d500dc21f409ce661bf33018b748fba3966d874bf96f4313eafea9decfba71d540ae0508161a3658c4762d94ebb3a4e228c45661315db30c20fbd9e20e24c044e4f0b49e6ec80949b16e0ab07f3d32b248b39f48332cc3686df05d29c170a7276acdd129259aaf018ae3afb49b6e0ddb9e404a492863daee7be71dfb11279047794e45f399a9665796d32d5e65956a13a6fbe992b36bf4c842f5f519ac47
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 9d1f17aab0ce96c4d83405d1e3baba1dffa86ecccee7f1c1b80b1bbf859106ce2b647ae1e4a6a9b584ae1dfc0a4deebb755638f1d95dcc79b1be263177e2a05c72bde545d09ba726f41d9547117e876af81bfc672e33c71442eb05675d9552df1b313d1f9934f9ddd08955fa21d6edf23000a277f6f149591299a0a96032861e
+S = cbb358cb77cb2f130b7ad636fe7ab00d1964ebd5da22bef0139a6265a15c6638b17ef3d84a588710adc06d0242085f155bf5349064dac7481ed79d62b3ed60121f010729b61bee45554bfd5d494afc55405fcc1ab8eedc9c6251d2d0512ccf2e4f370dfc523215a09553ed2b7a46e8bb0e63d1ef0b09664b42c35e303e2fc3e2142e53a0a11569f8dcd56d47542618e3f3aae3790e1f531240b52b0a89f2a24f018116e513e876c8079f3ea61210da71e481ab89934385319de3275c0d9fc9ab33ed8bed5f704ad40ceb364f21855a5f5cb1e1d2b580ee4724fdf61f308d7136160127247d4db3486170cd2183047f15c8cb54368085f595f6bcff02675d6945a1d9741768820bed442fb03d5087e793b62d3d0d37567020475268c8786a5e5385970728cebd6c027aac15240ace0f0beb6c29f656f6b3f3d458d20005e41aef294de9823722893021d9cb621b29c2730cda7b6703e3a66edac57019b8404eaf8483edf91478f294f88907e277bcff47fdce9ab7f772ec256122530ed8bc3b48
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = b33acd11fefde3f71597af02e49e821354a0bed0080b31a44a4aa1064531a8ff749bc3e65a51a56f742ed1e46c8167b18fb33e26812a34792f6cc20a0688d4eb63b2d7a04a2d13235a6e3b2c007e42aeeca071a5c134b70f11db403888dc483b67c632c63457d41db09d16620a5bbb1352ae7ed430f0616fd6dd421933f4aff7
+S = b1f3ee7bf9b57da11da3a557d311e0d00e474578d3d798ade0626105191f6db1d8d66da0a35259e40ff746d9c512478d8972cde6bf271f679ba2f8e49444002ba7f94b65ba9250bb5710587c9ea0ebf31802abb7508a785405f8ba7e0753ae1b95675d4a89227a93a96f3f273fdc3aa7fe48b94e48dec9ab2fefbbbec394a84305b0237232394c21cf31ae14e5b938e825be9ef35605d0200b9c085cab040833623e72fac9f59a2297e17cca08d3a0e11cecb5b35b3b86238a48be38c6c03f7e45d7c5495d55aab57bdf8edd871aa9caef624466b09721ac7d27a74f5ccb3645bf0690d0396fb56e424b716df6bd9e10becf9b7b10210266d0ebac4cded6510b02528ba2d3b5318b7e8f43462dda97b523b6f7355896cfd8989f8d9dac98e1f98f125d60a5d382513426565f3b1d1f305c59b2b7f659c41fb796aa6936e4e845c4ebfb14bb62b2883edb1580e68d52d62e0143410f5a5d2e8f7a2d82107b2ffcaa64dbdd32bff2d3228ae115cd86a27a3292ff43d165b174e7d77f6dd73402c6
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 7020d49c0b19cb515b193fdd410abfa3638fb66e2cf29208145e2608214e4debad45d1666bc08bfba568cbcbc78dfaab21d07d79e91fddb17fe7253bf5848c87cffd54dc07eef2ed55c56faead310e6508d82f04674973b6153121b82dd1c96a5daf27a6e98c4950f397f42ef9e045fa9f0f94b6af569d405ea4e226d11c4bbb
+S = e4ce05162810343296c8c774a21000f647973dd43615237b9f753c522d32aa6ce6742fa8c9b702b0a074ef8adbd17008226e7718c4c94255b01d7870cd5cfa3aadcb309612a7b0661ce1af202f7df92885a0f70886b8edec606b1923534c75f3cda19b156a2c90f6c412d33e2e0045b6a78aaa2fa991bf61417ce8f2c74a50aff9cdbcbeabab3e404799a8091e5ae1637933272b082d8abe7305173b0ebb619e4dc1dfc77015861c073e24de4dfc28e0fd95edf45cf540d7ecca1bd30cef47fb5e398c16e7f7e41ab35c932235464a91b3eafaecb1de97708a35c39730e58a39a2af7ac71959ece442e00d42e7c1f2885c49e5b799bec3d9735e1cdc85a4c3ea58b50524a51552f230525c834c705c1f1252f85433e42043d10bd5ceb42f8213d8e9db29924cdcd127f97778e75c1626b9fb68d6f0baac56d4cc30d0c03d80ac2f92b8ce2e15a7500b0710ffadc94c54a67a9b27c5531880a60491bfec5c78a7febed2c9b3e5c45474e156ad09e966e18f9f74ad2d60710c63e6ef36ffd478b8
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414a695cf2db3cc4089154364865e1f75073a39e420
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 856d1fe7642047ed19e96d364e5a2efa2c85a1041fb33b09dd59f038a4479b12c223a07c5b16d01367c58dbffa832e8bc8c4a5b4e8d55effd8cb6b50c2badf79fd277750d7bf80049249f4b1acd9e7316446213679df0d95355ad2e5aa0dbf493c61ec8a5f831e69a25cec33edc4209506f260b25a370e73fbed6c1ee5aa042b
+S = 24b57099a2e8840bdcdb4461260aecd17534f76d074c765b9944bcddf9b31572c1494b586d0da7f93e7d25fcae44804562dd13ad676b61e70d19fec98cf6dd2eb917faff448e29b951a77b1017a8650d0061bd77742e04a44c79bec6ce141bd264824b6e553a3f761bf583e231f2152cac58f71dc7198e675e364103012aae9b45a3d1a7d61cc25cadcf7d061bf36a10599a812ec279a996a486d46984ff3c10bdd6a465b93eb1796639e499d865f38b4de2b14301d01a359f36017ace359ad1e3c8c223ed74b00c6a113288e64a9c610f5f06d537edb11f520bb4eeefd055cb3560fd8b4d56311c5546b07ba1f3fd0d3e105f3da24f3bae8ed44fbeb6512fb66cf155e3e61475436b95f196f452e612aa9890cdb48938b29b624094e36f651bd305700b39176273b54ec9abb996e644be39496d8b88aa26dc5d4bafc343b9850c0201e44fac6c1ac69c4e408ad5769bf58fae1b8a88c160c0d193a2c807375a4550c4cf56c947a9afd9498fc220a469affedecda22bf44a8f6f9bafcd913948
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 590c04975accb7dda8c07afb60a7dec74d2ab36751b787c1068c6933a412f384266d871ba851d86f1417acbffd10e103cb19ae22196f2c655bc5152cc494cbe067b39c289c274460a53cb34791d511f76100001b6acd215cfa61d91c3e4655676305cb26fcf70396a45817f9e49d778c57072fb80b796d8c2b873d6bdbcf9802
+S = 8913d37eb20039be9bf34df63a3824f13f20324a3c2c2e7adc705f418c77d9be7f127e406d765501663b551e4482a177f58273483b51b3bb4614054ccca4a157eb6f4224b6c0b6e4e2b92d11b87fffb26237544c959125d2047165fc8dcc2d5766b6dd7d79abc37b79ea7bef2169e80e74237f5574494eff54b15f4ec7a5eed2e982a3b8d76b64801a37d888b079ac680b0833b51c2bb8a168c63cfb0a96a8817d8512fa4812eb457c1ed8ce0d563ea021a34e644e70689595a078ef469dea58a334207c6930a5ccd82307311ec25cc56807f2a9160b5d738acb42925acfbd4206bd92a24946e2a3fd8e04a1226e472be33eaaa5eed4c13eabca68ecef4d9c005b2f132eb827872235217622284833e339303162d866133a007e27e88af86b23c451a846eb393e05af713a59a929edd2943e6cff60aa906459c667595154747156c52c39bd369751a7a7f926bfb7e42bda447faa314a7593dfa4a06bc334ad9e52339917fc65598f06ff61ee6d7854325d40284e12505af8c57b857887f15d29
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = bbadf4bac5fa0abe2abf1e9993d33b798c5f7476dae4d6bb0e809be75a6da0b3a4ca1ad4d99e8423841adcfb9f1e0ee2a8ffb16cf888f15d513ecc0eb6e882127f4f4618ac433a137ade9a99340d37894c4b28f1aab0bc2f442bb356ef0cadd374c5e250e7f114d83495c23cfba69fb69ecc42cd98661f7810ceb686adde0a3d
+S = 257d8b3a2fb7ca6d0a78adf2b6e11dc4865c63888422d0795773249865d18519033508be2811d797d564687827eed35cc4c24bddc548e7be68a14cea7e8e0a3a6ef801df2d41519dbc056fdf5cb23dc60a9b8e94581a8beda4f4e660f699ba5a649bd5724a1d48f88552c3129bd08e2ac8b0ef60ecb938d4039a2fdc648b6afadd04683b40f144e474b8a99b3a81fdc623391eaba2111dc5aa812e3fc6b9c8f8711e9986c0c2f012cc1a0120c79004eae424dc4c90f24c8f52d536dbb50a101ff04498887eab4d2bc76902c2587a3b32ef3a8a58c3cbd11a9dd14055da56e7ba011bae74875fa631a0dfa524fe396b6a5ba1b92730adf17b2e9bed78cde226ffbbbfe29d3add1c61262c0ac9624f1feec48aa73de41627514bebaf76997b0350ea4d590c6cb59252c9d693020e7887bebd7a25f1769433d39fcd3dd46625208be410d50ae16b4d8fa6554be3d94a848ffc3211a915453b45a3328b001a5b605d686129a4cf4862b5e3453ebc42c2a11fe180adf5c12d50d361128abb1555aba5
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a050004149a135a3d21fc0556fdd6fa7ab0a3b1e4ff330f9fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = cb4029c463e243b9f901855447fa2af302441ee117a3622a359fb3ae8b356675d3cc97428f6b826b922831e7c3e458a91e357d2cfba45b5093198964c0935784041cf925cdfde7eef72e83ca9310fc3be75e73f1b5615d9bc16429fd8d68224267199694a50038eb30f9c3223fe8e05065a84a55ce4430b3c66adba07a1c9059
+S = 3f5e4b911aa319cfc15e4d6f7ee82b12a7bf827dfd244a5e57a52bfeb04bdb9e29a1cebdc4ebb2139906c42a5ea92a6737495d35d43ddeea1786420e57d994d880625f0c4f56594f80a732b549c65132355d56c8e7acc857344fc736a7b3168e8e892921c12c0cf8ae7a5d66a9d95d4180b1684ce3866024eeed217fe3d386380aab1530513aba18703fed501984820d8bb050229daf0467fdf13020094be24d8fa8cafb8a6774861b4a2a0e32373989fba555141d7113804b635c0ce480818ab755c87be02aecbd69754f68c3fea89dc854996a05fbd3d5f10cc7083f893297c63dc384a6376fcffc8cfb170ac7e0363489832e0c3e9b0400d928e05411408b7b12b653a1e4aaee79ee46fe892cc64fa21afa202c763b161b7d4f1c32e7bfc75442f1a3c31aede44374939b64c264f9b1833fe04172ccf818108f74634384bcf0208492fd81a77282a27987a9001754fc74690a021880b7f2324e65a084d88c3f4486fd974d50edf6c206ed616ed9376f1855a13b51c914c48b3bb0cce759de
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 58a1db581148b3b2a3f3c967d69d3feae7df5a327e122103dfb4276e640ca59b2b11cbc60c895888ce6e69589a958e51af92233658d6deb31b1aa4e53401a11d42f897e13f617634b5f22e182f57c150ee1f9c6aded527fdc96d9b30c9e3147b031ee7b2921a353fc246c0ae7f2bfe700d4f6cd8f959256a4f75b3550dfa253e
+S = 3b93e9611a492f19acd725d92cddbe696e97f29c5612d7a1c57b7cfeb7c70bae57cb9c75b6c611bb1ba39e48dc99ba9ebc091d7ecb5124bee1596541ee337746c86c6280a2db0f434e13735148d39db23e594ceaacb36bc29fe005ba204bca2d90cdb083e9972b227aecc588f601427c8977ace25580481db532f580cfcd54f56169fc2f31cd00f22834cd4ee3c6d9c5f708a9d26e10e341771ce65ee4233184506a17f891cbb633fc4571d7dfcacb949523f692fd44f08cadfce02b6fc54bc156a684c9a706742d5b2d33f45b01001e777ff13f3b485c5da6778526e1f80bae0a812d80cb2bbe2fcab984754b3ae9532e24e9c930ecedf50cb554ad345655e25ad118f40e9c729efc53c67f8c9e533ed434d57c92ee71fa809aadc3c6c82aa4bfde5df4b1a32d43981b9019c04ab9b32129158d302f780c22cb47249a1f767861730c4702b8f599b594aafa691d423bab81e8de32ce7a6e988839a55a94c198c8b10e432ba10567e8a01d264a9f2964016ba1f070592abf8f1eaf25f5c06f39
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = ad65063815129120fbc5875461c916131cf2d47084800e5270475cbe620d7959fe345228c1995d9befbb2ccacd2042fe11f4257397f4b55c558abb289139c504513c32a1146a8937bf5d0fcadad398acfc549d4384168f0c8a1d6be016a68f768fc6cc2a764fbcfc54f355dcf0acbf25c65b6367b5af4569f848936e571c7eb8
+S = 2f264e0f5c24603eda9315230f23de193fe6ccece8de2d6b0ec8ead9803798b7c66b9ef0ba801b029c86bbb35a743031f5ceaf19881948cf8e2dfb52a4c7353de5844863a8a6ce407a0c88dde7f76f76b8a548930f902c974462299a9065a2a9c90b639bf017f77cb699b2c255bd18999757ab616b39cca6cdbdcf176a0057620c88bf0727133b3c5607ea13a454b45ed8d29178ea182f54329921677f7ad9b01ec3b0dac78dd82319f5b04d9e64da052fa5b193c32806a3dc6182d2bd2cfbd7741130b5d6d32ccebf48183d8b552186bbc8f6f6ddbcfeb3ac86579794bbdd51d9b231d4520b7aca40379570861f09338185e120850e989b9f708fecdae37c95507a46eef059bf7cec22a8728d03cdc7a758e85ed2c7d78b61caca723a4daa85bc6acb5e72c59fe1ab459e9d181aa2c3b0a8019f510156d76b0712678019980f2377d1ad7f126fb81762090a394a172513de39d388bc52903725f20d476724774ab0debb48e33fd03c7b48765cf91270245b42416b504c97c335400e36367c06
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c1600b15747d006f8765132be06c17817a701f2b805bf6476a1dd5582efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 0484eae59ee761e0cd361909a014b9bc1260356bdeb74440933a1503e9913d3f5630f5a0ddd882a02761f462d4b813de1324973f70cd9789ee7e447f56aad7c4ceadc840ad5541c58ea1d2f3a4c866594d7d76dce9727c5dec1bab9632b4dd459385cd8db86586992c7d1b82b64e9973e7f63a0befaedb02b598b01026b8370a
+S = 74e96c2236f61bffc5830647a50f32a09b5170c586d38b83506c91f6337bed6aee942710a9288e17f8e9fa3e48ca99c23c8dec0f963f8a28c0a55db3d05fac86a67039a6c0be46d28207be9ec12e389bcea525386d4a0500d64a3d2b846cac4c5f9db7fe8a226e54e28e6524145680e8aec1b5d5f531e7cc5595e3f9973bf1b682574ba48bd42d55b240d2c9b6929b4a8fe8eb6493a2a7aea700c81dd8126c4f5cf2676adebfaf8641257d4281945ec771cdb4e45601ca20a19083e0844b8ecaba048ecfd2d76c24324f368f7c20563524271cbf5aa4239ac6259a3eef2c80e5f78ad3c7bddf786a090d7ac2f0b7e0fb5851c5017f9bb84001261038f79cad754d183662cef7676caa122fd0fb763944dd89de28f06fd40ad4721a02618b1a0e20056e265c8a2629fb57df29646df0ba56e94682bf3eba253a08fac1925d39561090d8f36c3b5068b26484e134cefaa7613898fb12c4a93122b7224771745ff115d4f70eef1e47c0a656ccec2d0afc46ed9d0fd5b29d151d23f59723d3818f1b
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 469ce940f2675abe473f931292c7fb141eb1d11ab62fcb1065aafdcb80b7fd9ae647451e871dd85c2386291154443845cfcbfe23e7b00b08535e6eda300bd59b4aeaf53e97a22cb90400655b74e83d60069264c397f345538978e909c2fa1899f7efc2472add9efc71151199fa9d518b4c6ecaa0cfdfc1188f6237003d6e10bb
+S = bb0257ed939f61ba105b2381a70acae35915a625a5728e29287bf0b1928e7c8a82d6b7ca4c1d35c6dc22b2c44895202f147390da4a1d3e64f416c03ced1f2523d586cf3b36046fb221efe1375fcc2d2ec9f1c0ed979e901573b2184385098a0fe27d9263ed6054410a3230f02b6258af4f183e82a4fe13597b5c805ad22536552b222c065627d4bdb929718bbfbc21cbd8e7d688a350ca2d36ed325c737af93df4993a9cc3be1d718cb092f48efcfdf21eb419de0666e3bad14abb09ec86890dd925c54b228b8efd5f491a5d52bbf508f15bd83e912569aeebdf9b570485df348e2cbc42395674aa69f3aeaf0c9573a27098253fb36f913b332f90466b18e2e78d8c504cf0eb835b5373e2113969f935b710013ba340292be2be396256d6c6559621fe96c1fab4b92e0908f71396b8dd2096ff1f2edf1ac6a31cb3b405e0ffd7c41b8edd1de01910cce15461176e4d2706665fab3cc1c9fa4e810e15b59d64e9a46588e0629d8cb16d60bebefdcfe58cd87c37c0e8497004bc42e29f024db067
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 207fe949bf4eb76dec39e361e5153fc593b59d2d10607c306681e8bc9aa19bace993689d51eedafd53c11864f8810b281246c32cc43717f844438c0fe013797c3f3c68afeab8be870a979fb074f20c2fe2214e3b832d984fb788e87d13fc2e05ace2b0269294ad349a2540eb614f88038dac06045629465c46b9c2af3c46036e
+S = 7fb366be277c3653fec8f65d741808e0e1676da31ea5388d2a87ff65d7e9dc032086be8b0f64642b937a8e0e563ab44b91e79003bd92713768b6caba087c973b351a340f3cafef865c6631da91e2eb55d9ebebd5d71c094ee8be88c43caa7c1f6a698070594d76d5b036ecdfbf0f7a9f680b56e6012230b1b91171d9fad3b8dc3c4ab88949acf036968169b9efd622cb52f485a2ed1bb6f65ed848761a67da1f67278a04891f663ce4bbab7f691b0ad1b8b4873e9bb4875d5627d581c262882f16d2c5f56e8614346934311408954b77f407272badffd3c2fadcb8a8a43441d612f6ba1d4ffbc00fdbf7fcc5ca0c9002c43f47f145ff0ffabb8c5760d4abdb6eaa01487555ff1ae4ffc632473a25831815f8e37b60cde1c85a537de9a75b5189fd5cdca65284165ee8d03082924feeea8cbeb72a1d5480fd2be13c4732f2f98ab7ffbb085c8f6c796993dc10b4c1187f32ecf2bb8bf592c3ae117be68a30e8c92d094e674a514fe9665643befd8e2c545a14e1b9f565eab37c3d913e18da9652
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c49c8f2542bf9c2bfd41d90d2ec3c717718ba9a1636f5ad048011cea9
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = dbbd09ff7b1c707c2bd52014adbb773ceb146aa72637c8724f5ac39fb5a5acc4e18bfe04be599e3ffe0f6186b870cfd2565527f5ae46a3d06f4bfcc7bf00317222e885959e03c6531da3d59e127b63f25ff9f94377d63b34bfeb6d893b4636df667da49a61427120503885450205bb05d0a9e879c70e1a0409df1dce709e4473
+S = 2e4d98c10e126e544d2b74bbcf0a4f03f081d4725a6661c0683d3612b01ddb2dd6f0391ef3679f39dc0785b37ac275f0d6841ed3a44ff7f6a407a085129a164faf63ff2aaed18ec6a5f7d27b48d017a50b24c8c4859ad2bb680ace5f3af57f2eac2d7337c0dd7403ffb2e8bac69dfdc98e62a07354b2fc93d03e499ee2d126647edaba094196b693e98cb98ad2817ba3f7f522c8f786b6ef82632ef5a00d5d4f42db6d26709909ca751aa8174037c924628852ce78e2829493d6c741d3558adcf713734697754e55e7b3bea0d8717da8aba2b2874527a0b3a8d2e1433344dd6bbaee1ebc7fa352539d94c6b45f915c6979b8e18be8934d28d770806c6ff893660dffd0e948a8cce11ac870507f88c1f86caa875ad721326dcb4f0d5ecc2d2538c4fabcc6c756ce4a59bcdafc44568787cf2bd9650486da8c85fd0b87794547e179e498cb6a5b26f71f9987d703f2d53418411c1f9a3a2e6705637b7bbda9660641c0eb037eb432b2d7515d1ffa99175cfdb8a2a4eed013b947faa4bf1c3cbd59
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 4255d5da3223d2f6e33c43abecea1ea7926f7052eb96a203438efb73bef867723f3f77d88928a8bfa4aae8ef83ff569ae3fb4a4a769d951741e40a1d42e33d2d57188ac35bfa593892d1a13947caab78b34b19a12184269050472fc11919730851891782f1c06dcb745a75718174a4a9ca06e5413474ded6385f744789c19169
+S = 6fb009ed4d66f18ae694d6e383196b02f4d82a1c7a755ec4989af1e2f7381355a5cb0bd7b51e48de878c74c9a2b359deecc55ffe4e67c8de5666f7a23144a7a67cdfb0a62d0135d4f58c07fe467f044c1ed33afee03eec57f8a0f83b451f145f1eb598d3997b67d98b5d05a6b28d74eca249af0129ee680b9055704d803f32ce93d77fdd0455f5002fab33b30bdc0c8bccfc6834c9a260168b366ffa6f0421324b673d7e697cb266a09e03afb0ac6fe89495852a6e90d6e132b54eb0b899bfd3d9b4b84bd4ef4b4566beaf2884acd26a27c0241f820d6612fc8fe9c5f4810c6a6a32c924a7b532b63bea39c535aea33d50eb388d5efb7bdaab3864830c225c642353228cdf3e0edafe39bb7d9d9bf8143285b18ad2c941ffaa67bf4d91f94ee1abdc9e5ec6f141ea0df5a27490c51d0b75e5ba470c9e02f071063f89f7bc221170f8b67203ee6997029d53848868b8ed144651071b14eb96da6e2cdb9b9f6183f548d500270a20bb1cb2e12c4a43c5bdb3fb97b36ec02617248242e5a59dd7e7
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 3a463bbff446f2b5057c50da18fcebff0f2c5be7e91e4144e91d88e2f486ea233cdab6ab1b10d15c4130fb85121d54564ab21f98e311c59b38381d6f6ad6ea56035ca67ad9567edc36fc9d8d3504ad206fbb9b5fd7549b3de3806d0ced3fdef0d8f59194f6c0ff1b2909bd5a4959fe44c66e58a58f8fcb14321cff224469cdd8
+S = 26502431034a0f2baeaf1cb7d8fa138b32d53f808d6183270dbcb24267c71564377a6d470ec42a02a7e88711c8c1e46a8b3868d15ac81146ad6c9ce9c40a1b09c8bada5020cc52d3ac2452a1b81c4ed0052a79c6e5cc275a032a816698e5f39004a340c13e52e9d672abaf2f5e230dd9f5a40eb250e8743a46414961d347a8828d5c1eb290fbad7eff81c7204bf377b9d9f4f8a2067cba6a6b7a088491cf42eaa8b201b5d8b37033d6db81454faea89417d52dc4b50ed920ad1e863f083e1f6dba595661adfea362d0e7c8b10a55fc58a1202fd222b4354c320dfa1e466e49625bc0c80dd620ba3cc2027ada7177ce44483f5dc8caadb3ff7d812524835f402e0d691e0be9bbac2bdd0dc6881e85b0ef46962b8441c89f7eb2a2d14bde8d2ff933dcc0db390f225f2322544bb95b34c2c2e59e6823f56c048508be7a3011a3130983185b47305477b19f3c701ff3009342c19dc22bea62b4bd2ed221ae9c2213b3026a576f8e25d72f9c72468e61b6cfd9530ccc1c183e101df9aa3228e8ce3a
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420d65f865a519cd429cc9d221cdce15d51363697e694b2cd6c09987f0310b5e8d8efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 631b9db77357d87e004b61ebda972db826db2b9f03c913136d7f5e2f601395ec406fcf96785f768162e849f867dca77667ab0a195a7cd253387c44e31776d20393a59ce373c638578a70aeccdaa8c78100b188f4cc21f99a2f3a2bd25a76781c24640d86acb3a668408c99517e261641b994ad199fe1104f185e1be6713b119e
+S = b3fc32b58ff28bdb60d7080dbd90e369d5b6ac8567f9953a3155e42ad86f671134b77d5f00cf1b686708da2dbcafd637b0e1c9dca59ee74b1bbdc339aac119661a2a1f3f837271a67c5788bf309f77752c4d62ddddbec71bf7b066acfd08b96d840cf4aec4c52eff42bb85038d78d668466458dc7d69621206ee831726f28e49a8a389789d39733abd67fa334c4ea1a39081bd1c086dea0a091e8eecb06d413799f88711084310c30cc824fc8f48d0a3ebdf481123a30a5535ef0c8649ff42746441bcdf3a7ffc23cc13c5aa75b2fd8a413b0cfe1388cf724cc105c182615902f91caacdc7617e349a553738d5a329445c710787cb08b87332a91ef8fa1ecc4f86a7c56d6ddbeb3397d2f92d2f325d29fefce33954a6620e3bee73411f11a152418c5cb6f37e0305530bf510589f2918204584a9126a3372fd7f915070bdba48e54c596d8693a9d18f848bd5a53982e8c8c33fcb3959ccf4a56d3b942917673aaa9246a5baff5f5aeca056287cebd950968308d535b1a62a5aed92d95d9d6c2c
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 50af2bdc908dfa76ea44c19958ba61f2deaf29e663434a30bfb98acc157a3c14635d6f2a57256695654c482f16ff193ea369e9e1c2344baec04d0999d0e81617a3c5c48438b137c2f64f1a24f818908aa8a16ecd8f1ca75d6b22082882b025be376f93b3db385745c5d79f3fa50fb01e15df207171044586e9bfed42d4d84f51
+S = 6b3f7aa014e45d369cf4cbfa86fd284af19ceaa355a00f55bf242f02094135e899529b0c64538ec409b60b6c9666f8dcc61fd6060c990954f8200cf6a477e8a114633fd8c9a62c0e8d1d171ccb5e09d360d42d868edc0bc0750338da5ab69f53ebd8f9ee99c55d9e1cf6bc9e9a8d10db7cc267adf5e525af09568c7d6ce2f59ce8c5be5562f2ba88d561f1d46dc3aa765b3a3a2f5f156177d5de5e959f2beaeacc2b265fe5f7f3638db14a97d673489faf35be8579071a09e46f48967d46e251a7bbf460fde2528e36709b5b4e13a51ee53423bd4059f38a1e3dd2720dd9c037fb6ee048ecded10e5d7c199fc3b2ea4404110e5a283b4feab8048487984c6972ced45ea31b1d262f0b071ddc146f4db71cf43b56ff887679ce39e9a6a3e449b04f3d6bab80ac393abb472dbab9ad52eea3b936ff414b9eda99d710e7c836c86a60755b65cbc0135b71f87fa96897c708cdb69d6c6d6d4ca5fa850fb6ad9b2c0eb5483b3641f211b2bee68ef6e1b32188099e7752d6776168adf7f0667f7b2017
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420e4a129a7ddccb2047e91b87062a92c5672bd3bf6238b5d2ba1175f37f458790d
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 5c78db3e64375eb7325e70272bd431c10a71e34acb58f215c987313123ac67e1633a0a4c62bd4a76666b526f8efbcacb70baa05100db08f8b40ec10fe5559abb791336a6bf660cf69ab7b17ce2905a2e07ad9dd8f755770e42eb93657cc0c9e3e42be6b342dcab1d166d18b6ee3aead418736245796f4841bd43309cb194fc40
+S = d3bf9e41c55375a032394a403ebe35dc800541f87ef67f9de42b9a386b7ed0f78403eadca167e2f49c5332cef85c2bd821511c721ff4b3bc3fcece51bb10921838384da4af0c40c1031617067656cba8eb2d2b7f1744ecdfab6874038163a97cd08439aad0b8f959364a0cb0154a9606289909a1a6a486030abd1dcbbfc113ac34bace0b84f1b7f9cccba5dbecdd1932f7993966f5ced9187692d03b8dfd99f87c2903d72bd7c0acbb942c6f1f321d43a357a21f6fb6b78f91b92346ec2e577cb8aaf9e7affd12ee3d27ec9dafe50b5cc874c374d2e2c1bdcb22f1b6105035c393e4f8f23660e2d54795757a0d1729ac12e053aeb239b7368eb991278f3a0c2f72c551cb90b96cd86905389582641d6c029c6622b2f7db133191966901d83dabdc5e634f6c8ae59aa54e6c0c2db7a1f573b825102777fc8961be82a624e5ce01244ae8279794fa5ab2fd62590ad8a00c5d0b0ad11a0154d9bbc2cf129514bf193c715e49cc75bcf8343ea017906dcab061658083ae11fe7247ec95ba18cca761
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 275a91aa97dae189c61fd1b7854d49899d9406d958a8401143718a853103f90683d088b3a71cbb13dfb2836144d662270a7acf0f05b5dcf56c701640de63ad73a240d5ff332d6b5cfc78dc57608643aefd0dd1da3283722cded7ad1b6b5eccdd0c103e3442f4398ba5d9a441e1473345ffb5d4e3e6fc4add210c17bee2dea06b
+S = 270c4cf3272ae89db2b9b2be30ef1167d1b8b67307e40f97c81c3c9ced0924ac971d669e6c0b35ece58b5d4d4fcb4fda5776f81e99db9f8ea4ec5d65ec960f2feb0a4166019e5bf856246952a9a68567703e505dcee51df9827c51dfe6b13eb6038eba7cc3f3443f0ef6f28ed06fcf272255ccfb31f3a956a36744b878af8eee1eaf0e3ff1277ae602f6b3c1940697d41a5acfbe1bed9abdf73f7882c36647f2f8566d3d5eb24ff8758ca4ee72405c4f9645a2b176ee0dceeed37e8decfe2a3894d6d2118cdb7295593837e2ef96335066dc899a44dccc93ae1aa1a6d2548d074be21170e3cd6c73555bfc3a95897ac9a4766573008ea7559a08c3ad3c21bcdc32e4dbc7c5982f279b036bf790ad0beb6b129d22d834bbd74a204d5d60bf39a3fb4ae819b772dba0ada94a45a5fd7ecc79cafa31dba6762b5b51ee95c0651b63309004923b77c010d4b6b3df457aa0b0e5507c3d804fae26b0c384c1a34d1bdc998005226e81f2b9fae100776f5e3e410f53da6898e20cebdbcdbde9efa1acbb
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d0609608648016503040202050004307f87c39e3367aae5759a4d5de9ef2ce5f95692c59fe337dc4087aa11be86c01655406490b00224111fab085cb688bac2efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 88af470625e6b5be3358cf6a8698a5655ef321838f044746df83bc55b05e8529df0b120aeb1c7b3a5a1409705879f887a22a7b78a2f30186db5fb7b888cd4e8c80c6feea5d8ecb57ddf9076b8980188594947bbd0533091a19b87906e2f727fe3589138ec3652d7d86b0d0455fd78cc5fdda283a00ebe76c5e370b25060498e7
+S = 879c4df9b66227ce30e6403b620a488c72329b400ec67667a600bcfe3d0ea893f3051c8076eee81e0fece30c4153552ae2b2c774888657adb5300bedaf4940d6d6ce9310a476093b3590fca889e8ead464809be4da3370c21784e4740453df999bb9f7c290ea16e4b0e4ca666ddf23c757474fa9b0dbef769b1876e1eb553ee3a1c14c201c101164d5d1e5f628a7ebaf65c0f0f27f239ff67a4fe659d347cf50921b5859d79d86f8bfd2a25eabfcf76eb606b4151516c482c74ca3e54ede03e99086e61c0708e8ad9c94c1fe3640bf811f4e2c0e62d17d593f2e86adfd0798f04616adf9367b0f77f40de77135301debb490bfc76ba710878ddf91651a5fa025c348b6066a49853d6ece7bc79cdcd8ae709a77b96701c1ba9c4a91663e3790bad5c5c48017fcfd005a1b03d47d07dd3c511aefeb4c766dd19e377d2d82329a222b18ee0899e166cfb37c0b1b3226123f80a33c096fa4ba784719c4d9e52e60ccddb6da8575e705a36dbee7d97093f830283c71abbbb85c06daa913f96dede4ce
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 78c938a5628ba2973c2b793348ae3857f599e83bb26c930c026cfcd7d3a58da90c3091f565b2a3357b2566d424db774cffbfa08c50df4f9c0b2746832f6f936955b9c3f989b353095884677d2ac4be68d3cce6756431ac86478bd79a8b7b16f47cec367a7798985bfccee3f40573f6f5964821bf966a9411dd1f17e48ecffc93
+S = 4009022b370d46f9b15af306f177d7aacf5949bb58b68c05680eed83ef5b35b29c53f781ec1910006c4a7756d1c0e67ae52e7599f691352ad5c052dd6fa7f33121841869f1df1884489b18f4fcaf4b790f6818549b26f2c764acdea5113427c0aa6f0d0c3c688f10e572adb610240ca1397a96964861a562625f1a55c2d369017585136aa6f473c368d64f8ee85eb21aea3de696e3a258890c458b1434936f48c5725b6c81de0d2f9019a4ab27724526f64f6ed1e1dc09f1d828c1d6a1cb4c593d4e554e714bf55ef5fa2915eed46497215957abfe3c92fc06dfd73add5c2046a97b50c4d2366a4ff6c03ec4ea2e916f58240744456cf57df158a7a4c3c0bfa9cee2fe72ebc2d792a99aedfcb7070841a691abaed83bd55df0408a8555e8c58c0023d2000dd7589f9e3b5e5fc9f6448f47e870ca13755408fae7eaa16e2dfd4d41b4de4099b5e224222a520b87784b2679dcd66cfa94077b9c5756190bd25d13fb40015f1bdbb73526ab6467d0eb1aaa458f38adfd539a109eed0fc253af8e8c
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = b82dc25af8993613cd5f5e6e851dad20d155f1d2831f3278971addde70a82283655b9aab7caa2db075e933990b78d9ed763ac6ca3448ff3109e708a445b84df3452fc0533c46c2b0347347444fd7356953b80eab6531cf22152818ff9b818c6460917b79c1d6bfbc0fe5e398daa38b3a6fb80fa09f416af2c2c55316fc6ba97f
+S = 03ebbcc4ce14c87345290d77a652ddb0a27143e11278b4083cc33a70e4395dab1dcc8468f483e6b8fc461e31e1d5331fda53e5ea595950888d05203b06316f7e5bbec3a2a3ba3d8917e56a657d04c0a8a8aa123119facdd323114f9a1ae78ff5d9295b4bb244443a4e3ada7c00985e74de8b295dc898ecd6c891331cd458a040edf8e8d2d9aafbfbad55f111265723bf9b04636f211d853be40c9119850c2905bf665cae93968363e82794faabcb02a2f1ea1414ff05c63c3f32832e7d786809603b41776554c973560e69c3d37eb295be53c5b9a9769dad97f4a99d15e11c5268e10387b1ba13b198165f78423b61e2c203de534f9e331c004bdf85d1413896d4deb83a8bcf8a09c26f43725ae9a1f0f6ebbba092803e498a9fa5e3d15042964596817ba275fcfc89cace5b0b566afa19fc3897223b2eedb48d1d5259aa576f3248ef1647e6c3bcd5d3f88f5894be8006147a4595d416404f2de4724080bfbdc5dd58262ca15f1987b09a80a2a38c8594e1d2307fb99c1336f85e7c0cbc8ce0
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 18201d59ba48bd77abd33ec87a68c1bf5ab93b471aab100857b7e4e6f08fadcbba050da77529e0b5ffb211ffc8a0b124861f4a592aad70ae127f9a938021309a4b5ee57ed45f47653c179462d4ded03ed55b147852a8298a6ab1566ec2dd756133f14ce7bf311b0fcac872f886694594b03742ac7ae26224c813bf819e0ba5a8
+S = a07673ffcd2d28c4dc9ee2f91ab9b1f7f59aba09779102f5832409a3ce9d9193ebb54fc122018602ecf9d52a0e29c137e7a4430253faf49ce6a5f25b7eb7245e2dc01aa870f0061cd7857a6f58e765fccd06ca7f35cd796aa016bc0198583f86ab714a044e68c4827f5ecde03f9c9843f3fd5c8448bd039b5ac70a6bec0048155a11e55f60edd315a560c5410210be96baab0056f0ef9404333d068af9a814b5e8be1ebcbb1cc746080fa7b3a09e200426188b14488cfcb564a8327eea01c0c1a1681552fc23cf516f600e596ff6bf44489f07db4167c02028eb6295c769fcab30df726aec31af2cef6a26deb01a918e6dcbe6bc16fbd21092a28418598e958b99d7db0157674ac564e03ec10bd6a59d5a87435259b5d74ecafa3c0209a6c20edb7e874f6db5fb83019dfa7820584aebbf93740849b5e63985b707e891ffcebf0c45f827933808d2a7374cee25694ce9a714f433017540c996c0b169a284a5b1b2d31c954ababb6f75d7dd060408e74bb09cb9be1288a9b52127fabdc2de942f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 6c49d5bc93d861ac46788e3c93d6e815966b90248f46ec89370c9db0553db1bd8cb81a2e77825fbbf8c39281cc11826063f131a2ef9b89ddbcfe4a1abf0447367117d289dee475c6f85fe32232072db94a6b392d66ed719063c6b8846a4aa2a0c46de416ef870993f1546767ec3f52e6f3e08f0e1cc30b6ad66bcd357d962ac3
+S = c35cc19c52d8727b0e9945942208234a2c4ba3f4d4accaf9b54fe161b5b92537838d74a94c0aed70e58e99cdafbab8d6b968f57d3af6b7a49d8592a4b381635f7ceeb25c4efa0cf8d6cd6c2e8b751143f11ec50956db690802fa0ee40640badc70ded68345255b54a97dae73b340e10af6f546dfd395d3434b775c6dfe29058d6c3b9531e968091f8e80f9f4a82439890f7435622b3fda11eda964dbc5c94f2eb7b66ac1e17b6e4bbb5a77870e8f03af62920e64ec059e6fd037574f31636800f53e506570f5352c99f04985337819cf47e8cc54ac38667e3406597f66025d05e2269a77b347f02129b510f38f898a7a79a71dc6126d3db62dc3dfe5faf7e917cff2fd6aaccec49eaa0e8a35b4bee78ca043ab2f860155ac2ecf3cb7564d8fcfc913653f6392fc03a675884062217f23543d1030704a733d077969d9181ec555c0f3808ec7d6bb7873787c296782a8c3d374039ed636037e2aea56cd230baccb692fe46cb84efcebeec031801ec10ea4fece8940ca6e4228bf5aa40206efddb8
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d0609608648016503040202050004300ba6737418933139584032033536d357a432e5e4b816eea001f2b4d47dc04550e24f47ea3060631bca744f42b3cf9675
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 08845a6647884ae71378c1ea0ebb9cac11159eb121cc08089e0a6ad0be83b8fb3a57a052473a1bb9c8d243b5c260642b10a3556b58fa096c3dc86159d61c444d5f92f25c2f7495d2ea251abff8c03eb336fcecc6eb53c6dbfd630226659477ece0fbf78ae77ee0b9e239ee10992153cbebe70acac22068dd46a2f43e5131785f
+S = 06771fb5a09539491074d33f227cda5a26e630075870b00e84c0fbf47c98e60a986d5441ec0ed557c7b02db2394951b61d3ac76a94fc87b21ae77c082bfc0271c321a77ea020900fbcb7ce8ed40016279b7462df2da6e32ce0975c3a5d05cb03dd0e97b533f3bbaa352d579a2bf2d47fb72568f2a0e06a514bd1b3475db260f0fd040626fd8681914a28d49e6566855f02ee2eaa5e1e3e277e00e677c60c87083fa88785d48f7970fbf5e835e0b2bdecc61df27ea9fc7cf3f510cb234d25405c4f9078139bc85b92bd0e8905be80380188d61d699a7c7db0e087932c2cadcc6991a34dc2a6f9c2e9b659dd1527c51d6c41fdf23b5a14f5d8f0c3ed2f28c08223ce4450ca5e896a2ffd0f490cf2495956eb0257246afeece291b8ba7c373caff9eb52ab90462069d20e3b09f1e874dadeb2cbb599d2be0eea434f70f2d26ada7812f58b7edf20ca299ec53762943c628ee31891c26f69eab3242cf0d90ef1607ed56c19ff5af4d4be35334cc013b47aa087935a855dc1ff62ac5be945978d8913
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d0609608648016503040203050004404cfedf114d5b9205c1c8fa9a8d73b55d82c17feaeadcf7da87eb11bc021a4b55a0c0e4e232dbafcccc1423db05e8a917b5d86dd9854d2f9081c5cf7744d882e2efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = b2f46df8613ade16f5efaf19cd04d7ab3a99c804e0cdf66160d493b1344a9d91dac61b7a34b3a4392f5b20a0a345d37c7ac197c715c1681eebea267573eb9709450eac967c0c05ca5e26b6fa3f714c15a2720bd6a2ea7a3d90f3223fde4c92bd3bf2a6b300f009b2cb77f99069314a5efad3ae9a4ff233a697170d793b159695
+S = a411a40f0b95e8a447e09914a31ab52842583a1a90479435bea0bd20104c6423ec3ca53a42e8803d172996237e35e59952d32ad3484fcec66fb8ace07034928ed162d287125963099eec4b1f59dc835a1ca02a658771a64e20a5d4e2c83770a11438b1956bca7c586595f8cdd28f90a033b22a27f10dfd6a3de68ae283b0af9b9fb3fae6963b9177ab6bd03b7ccef9e482c3c6cfb50434212c341afadcbb8c62ec4b63758c2ff5c4ea4e6625f8ebe1b51dadfc902c572d7786ff0acc39b82a3b3dd14ecaece9db85dde3d4f13cf7cfcfecbc5de471316585541a19270c3ac94aed43087b5c03e8da4f5ce3ab7cb10567d57fc2564e2df03143cad78a797bbdbe86e9d5d64f9cc9f9e46a288bafcca13edfabd4c1914884d6984447873d033a8164346b34405c8c0c84e1ee88d480d3bfda3aa075007d7647ee8581bfdf91912df7572bb8ebc9ae22f8dfb308e983788fdf835e415e883a401cf23a426da1b21de4d904b5d52bafa91b969f36811e829d8bafe39ed4d78e2f30c2e60038d96a95
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d0609608648016503040203050004409f24b226f1c31a5ced2822ae473ff80616c976eeaf6ca63f2ffdcf92238baaf570822977f1c37aa3b53a03a0ae95c82b8de631b9bbbd0a6bb6623d9b8ef18d0e
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 68f05fb0d353897bd65d75d3b54f34199bb8e5803b8f78c5b87fb71ac282866303b169a4b95b48baa4546f4a228fd9f899efaed9155b0a2a321100423d3cdfc596c8b31b58750f203c2a0a1dbb8d88f873d0bba7cccde9eadb566f3a87c606fceadc45fbfaca671568884f35c86ec981f30213d4a90f9c6e7bf70beae8498371
+S = e7c726b4bc65c98e0468e9e20bd38fde581f0975031c56bc8a1b149724bc313442436f6b0742aa96fef392f24f4c6e78c6afcb17a9a70a686c3091a0a746f6e427023877c5080ec23d50c2c8ed063b5d435ba3cadfb0786cc0fbec7d4b834e45ba3d4ba19101beb4cd0851cd66dac7dbe6028a5a27873b81580ef817c0cec52dcc99e5d0a48400109525813c9c087b403fff944c08febb645d36d0635c817d543d319cb0625fdc8e098cbd64b67c1981da87a4550d6bbc49d074fadff82f56332679baf1861b9f09ceeb8d18351dc7565af1e4729dbfb265056baf28ddd980dbdf512e9d86faa6acaeea1744f6437e30a9ea6faafffd6a813e255215bc1ef3e3a6d2879c763dacba1af4e657a7aa19e11143da902ee567fcf6ed9bad15f952e7087d1befe7bcef6a9f14fb7d7cbe9e06ff583ea888b27a0781c1e1c46dbabd14d5688f25cab383b05c79dd4f500bd2be7c647cab0b12c123a0257cda1f0dab31d42f70b53adc07765e583a146ecde0f37fde7c0f93e72cdc56e734577be3cd1a
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 98ccc6f8347973189f124ecceb360f429f1aa6f850ce712175c2b24a7688403d06db7d26b3e187f4bbadb302220837f7017126eb2162a2cbc8d54dfed3070048057cc0ef9f43ed1d317bbd86af16e94ac7dda61d72b4d7a5ca2081231b067f563cb6779d20270c5ba884559fbbe88e0599670ed76c4d797821aa3703750e252f
+S = 039f309c9e084736e33c0be61eda376c5ab9759a0ef9e47f9fe17ae52cc6bf878cc2bc6bc3dbd9986f9f1b971a5eea3377a919922aeca340d63fc414376aea9670aba138a831f75b4bc63ff3b1964a6d732988e6d801f4bffde8b36fe629e57ff3f6d6ca425a8b7d23f6f66d647aad60e60819cf00afea8003bc56ae59de98a4f0e87ce92f4a12e3641a7b4c9dc53027659f0257c3ec7e013e8396b5a006ea8b1fea2eb25132618f75f5903640bcafba9f511338fc234e1f000cfccee896194d0182347e979afa5b03402690f959329ec567bad325172c913b4575c1c46722828a99e9a304f016eb615664a43ad1bdb26e99e429c2cda4926c9005af24de69861850b6a0908347b2e72474df05c775b7cfb2360df99dfafbed216844931117462497b51e40b6b634863eb5043f001b6d3b15e61f00de1d9f012fb774933f502089a213ad2eb89cd150b46895405f087c5c93d7a9fb55bce4a2d93505d81f2966ecc6e0386c1957451d014892087d978422c612d226c9dbdad48a3aafe50bec47
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 112b7aa9fec5c7ac703a49c298c4e29586083296f79b099e6ec422d586840ed486d36e06362d6554f14d4d01fc39a9d2167e5b7350bd18161f66185db0c4127a7b3a67951bcc9e6d5de010439746e4f43b773e65ab1ab4234fcd024be621fea819e6ce1c56aa5841db7cfa4f11f67b411c7a4233b0bbc60f267f4668cfa4baa6
+S = aa3ee99d39ad0332ca48deeb68b5966962018906f1e2e97d0d711df66e600fc875faf8da141212ea9bc49b2934f19bcb26f819b3633381b23f74f0c1d486c8fed6f6c17cacaac222e55c8c534ca2cb3921ca6f0cc19d045fa5456b4ffbc496d0d3079f19d93bba5600048b783a905abc3f30fe4b33b057a203b5f9d01254bdeb02896cc11b713fdca55e3ecc67e243fddf19130e2f3c79bd984558feef0fe877e071b0a13323e700de83244e2bcc09a602eaa06bb39d832d58e30450dcd96b30052778c07d4b209d5929bb6cc80800c95963a24bea449189301b50b5f26a899739dd0a4af6eba05e7e625c96cabda3beb2e4b0d11ccf72252b2d524d76a104a6dcef635517d78f248c78837422ac900557e1671958116500c673e2fc9a08e40d4eff8d44146f43fcc5f4086d276ba026e9953425a11b7be0036ddba0648f12424c3359cd8db8a0490b1bab3b35d3550840b4937ad1986aadedab74fcab27fec7561ae2bbcbb16d28d173efdf049fa8a1daae66db51f4c03fc91d1cda85d2cddc
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 078ad6bde08572c73c5e94bdf0f1efd12da3a8fe7c035027236acd3e4ea86edd1bddd92ca601d012b7aa4e4e543caccdb49f54e35ecac7ee8b03b522a1b09957fe3ebc4d42dd96dcd4f9f2e215dba47749c9ec7369ec21571b21af638ac6f05d45980c4af0c1e6db2f70dcd738a803cb9cee7dffc3e7a735ec6c2541b270cc6b0225ef71939220f9ef35cf5c5b0dc291e237bd456333d803d12883e0694b2e891a3248ca36b838a8de27e154624fea5149857214b15ac4b4d67e0ab944ff5000552c66f833239f3d4c27a76cb14dd181d3f52a12cb4f3f9518dcb68c9db923e677d6f733febc93152c311880205a5b73ef323c07b87cd55549156b0452656f0f11a2c430924f426a22117c04dea477588fe092bbad1a4bf2a0a7b6befcffa3f91f4d308ff24515dae15897e9ab00bf755f9a366057b66f095573a9f881bc48e3711de800b3c0155c976957c40eab8834c7b7911d426fd7484e895fc8d8bb5ef7b562da7a846fd6bd013cef55ff3b11de43fe6da0c90b59dba4bb060ce4caf3cd
+Msg = 7f1b83830b4da729242205b0e519b5243d32442d45f5a933d1b57bc54616613cabcdc99b02a7ddbad8cdb2a41b46c33d2cbd9f283585dee7bdda5944796a9bf06514926b14ef8a23448e5de0b682e35f3d21b03d1486ff1874d9e9f066d1dbd3d77646b9ea2c98ad92ed6c2d5fd6fdd498e5e1368b01f40c213a9291b553092b
+S = c8e55b1b1ace23e606465dc81f6a349ad61d2b8a1afed31215ee6a0c8214c5366a2ce18cb649c4bcccde5ef2bf4af51f093049d1ecfa5f5b639f7ec62d5a4cbc505d0f11bae2c16d8d6a61a4f1f9613be25d66fcba03a7c405204cc816414a296787e5a1462d12fab51a829bf13dec500da689520ddddc305152021337a86b676545f8202c5f936d9cadeda41a111b65d9174488419dd19da5d3960b6f59281bb2e90b4c12891a1d5800d0b0a932bbc95639b130dc7d03402322f7cc7e06020d5124023b049c61cc6e88b345d0a395c80f1f04b7760f0c526537f4d4c515696253361a0eb03c3c5bf567cee736f63572c85db1c7e5d016ff19c0e1d38caf0f7569dc00e3c4301be9baed19d45aaa90ab7204c2c70191926ebac319caa27f55e5e68b57ba4a70dc153d750e318099c85359f1ebe70686f4bbaf9b9f6de3459cd8c4a7bcf8e559eb7c68790a67b0951554d9fed9b5c396f44860ec61cf0446cfa8061b19c72a34b62be8f34736fbf14fe556ad57aea605c60adbdee4d3fafc5af8
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+n = f33d3234f13272c3b2b6821ce4805663ff2e8b0d2a47de363d97fc9cc879cc6b40f9e53aea695dc538a0d2b558498829aac327eacbcd889e172b34f90745c5d528b7e82605f1a58fd228ec7fd4b6f476f393864f48dc47097c8a780a2ecc02f748138dbd7df99c52d822a2e5154c6047fb0eeb4f49da38edcae3c32d3fde435f291f96cad1e09e1030ad7efb4944b69e074d0d7964becb3cb86238d8d293bef3030d141d14868bc21fa133e9de1115f749991cf86ef506e663ac162b2c8567ff131a6b467a6f564d6c588860becbd88970354198ecdd4f1f4baee8f8bdaf7255835385f5673625f113550b123628a0be3994d91c3a19a82e5d73448dabf684ee6794fba7a2b1afbee0287e5a11180c29ce0896795d52ac7f408fe28e8e9116fe0b61a1083f95c5227d62d5537b5040b79e21b3a8e83c225bf3efebb2f808541e97d28a2468359fc60f588e74faad611262064628a25d8d61f9d03d8b21cca515595aaf2343a759b74a6a8afeffca139a389aa281995cd18e16a9cf7b7ff0dddb
+
+p = f3fcc6aae575312778d9e896acfd7c1aa4c5524f20453e8bab255363164afa7124b2425587a077fa0bfaf61b12ef3f0540dc4c9e777122a60610a53d1d75b0a5859c654a8ddfc2ff4860758bf5a6f264bf8bc2baa7551eb7be23bc06978be992fc81d890e07a3abf95d20eee3f6bbbc089985cac96395b473b2741c66bd2ccbef228432f66b906c15b19694dd786c29f06cbc17b2e6400dde4e3db85819382b3d05a4c3009f092d40d05ed5b2e0428a214e15a7aca09b47120b9ea6cb4084fcd
+
+q = ff36fcdc519fe10c69aa0dde2cf3bc72cf2ce9a54ac063d809b523f4e5d7ddaa5413d500dc21f409ce661bf33018b748fba3966d874bf96f4313eafea9decfba71d540ae0508161a3658c4762d94ebb3a4e228c45661315db30c20fbd9e20e24c044e4f0b49e6ec80949b16e0ab07f3d32b248b39f48332cc3686df05d29c170a7276acdd129259aaf018ae3afb49b6e0ddb9e404a492863daee7be71dfb11279047794e45f399a9665796d32d5e65956a13a6fbe992b36bf4c842f5f519ac47
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 3330bc3d3eda995522e8849c7e8bb5f3f6e895b3d7238156febdca74f62100f26079707698c6eb1d9530c971119a2e95ea7a8cc3c9e869f901f563eeba3d714b4ec06b18f3edcd749b00b88a188e39c0845ece31e07b265efb872920955238e2c5acb60c9877c7c2fb0057cfdb8f5fdc8a3c63e6650540efb41e24f3d188de1d
+S = 5949a5007545d28832b13c6c0a453447eff95e2dcff9e403db83bba0379abed6d503394befaedefe578be085622fa73ab8f63af52eb91dded8a0456df41651cabccfd34250b813b57dcc4535edbe0901196724c0842b951ebf3ab469faaa51fb22e5574696dbb57614892d21a889224f6bb0da4b81b8fce60499b8802b36f1576780e298d87b71dd5496128b0c8fbd3f1994385c8029b720cde1317db984e02c0ee77cafca705d4be54fbca18c4f5ddf85eaeab784002c8d1fdf5e3794d94c5c6c781e9c05eee22e4c1556d9f8f6215b23d5c687ddb79af29a280a4cd6be95542709f423d918d9147c2c501d3f6121e942fbeedbe70dafaf76819842d651df018959e586e8ac4325a5e616c3e6474e1640d259c55474366761156aabd0d144a6437e7584bf33089ead0610f9ce10dbe39fa93ecc7665082d64aac474432689758cdb092757a53ee5b9b4eb3f6ec3589074248ee547c6fd203fe5bbf217974f1e2e398dd4d1909e85146d7e1dcf74ed9478ebd414268bef406228ef21c80ed1e4
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = cb67ebf8f8adde0c2b0640db1f4668ef866c27606577504abb7b777e63f3f8783b593c9286f437778ff235d990b6d767d17358f914fa150e31d04d79fe842557713fef44099dabcf69bbce2b479243278483b05f9c32fab441980bfb4354d3f2b3428c78484f43fd018c94370c81b516e7c3b6fbc5c9062533fb3a6bfb0c0a31
+S = 5e8e0eda2fd7477143e33826c1f37f1091e766874f8d9717ada2754610aee94c5bdbcf939e710a2d5bdce1329aaab8eee0a33ea8d93ac243e80a61f09fe31dad8eb291525dfda5110148a9041551c4673db5edb4d3e457e2ac8834bfe600ad9e210a9dbd238f8811552a5a6de7ac23e7ead2746cce7358e7b0fe27af32e204bf292e7be24536a1df8e10712bce78d0d94331de7095e9f56760d7e9e3534b0a8bb30357e2948e2e649c489e916abb399541067f778a21505e0ce4e43e3a64c30fcb8a22c575b2f63868b151e7c0865a52884008477d78aedec9b950bca5ffa93dee9c7b8234a054b61d2898a4fdafb1cd2008635ff56744d0419cee15477f544caf2b264dff93c2ef060fbc7e062ea29d80bec0e74287d9e2c0adba92b5592c4339776bef5cda132c83f296810833cc99119aaa31849ddcf62bf16c45f7654f04ac4eac75102e9c5b79738e7d405caa63dd917f3f199d132169192397198c67551ea78339ae376502e7e4ab23e5626c766fba9916ecd20d15fd63c75e4a927ec8
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = fc57235b4d597f5a5380a07aaf7ac6074b17d75ee4b504ffc6fcaae4d7cb7611d771cd6de6216bd047a04a5d6341c5121113fd9d14597c71e53a181ab4ba1acda9e9a0446f5a40c9f3d7ee9069532049912030f6386301fa01c4e573656abecaf9266489efee476ce08e56bac99a1fd553a7371057badcc2a101d999f4c1aa30
+S = 5b53b1a1fbbb8a28bc715cd607a699caa795fcff045e660e102b6c51e0daf25a9cc0d0639c1bbcbb9805904cf16ea3bc26c18f58a3702f39a3c1cbc5e6dac954d65d102e0c44345704844af1b8e3f15b7dad532192e35e27a335bb67dd3367c828b7eac524e1fa3a1db556c0c3180487ce197cef59ef05025d0e0c7dfb87fd9da457d15688434f5165f16205a8400849118de58b6380b807a6600c698b2553979c7e0b83ca200433c5b5a6155eb6b37ccd8d584f695a93e2b1a3f933e3a0997c18ec63c6e90c54f87bc48b8057be5eea9131d8acd848843fb3aea56882c414258478548a7806de7db039d97c5c440d8a99923cfd7c3718046fb16bfe53dfd157be94edc1ce944fd5770c38247d78927947c06d113759f4134c841323b3679b0e1b4537335d4a16aa2ddb01fb1735b8f8d0b0107ae714fbf727ac74572d355da37b997b9a424735f535232ddacd026814799d86b91b7701753fe1952651e991a1b8357f43ea06c043ca1cd57fdec28ddbe011554bc04dbbf3cecd03710d454bfd
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 6449afe8eb08b35e4411a1bdf1eab7d7cf0d5813f83b1063e714d376dde5852e84c1c054d2d3d18b31f20382dd76216e8d4a36b8554397f2cbb023106933cad532cf4c8b984143f79e94648c3af002dffdb3d35bf5c2f736d32236a349c28a4ab69bddf505fb138cd21e4b43cfff6212676db966a1613916468f9498463bcd75
+S = aa36dfbe785a437cd2c92b11941827bb4884157fdcae8331de98ab8d3294ce8425e719b3b0e54eb27d7a46e9729ce18044880a18261d28d6c10641818d7dd47c421d748c984597cfcfca821f8c3294da53d16c1af99135f750294709b92755a3f5051e033ce3f6df055a77c628ca952511a33b2a1e6ebdae047d9c7589c8689e9ab16747dd4788d023315e6c98f2f060f3bcb655d487afccef512d929da03e0e4d7ecc2b7715ca61cbad3f8fd8f4383391014f14fb414cf49347ac60c01b713b6dad9e09e60b927b261aa5877a1d5b0e76906d40bc77cfb41405b93a3c93fc2ac12aa08e44b577980e2ffdbce606aee14533c8161c85ce8e4493a8c1aa03f708c6a4f84d44f9d147082c1d6d0c8498e109d4e26406ddaeaafb9409cb2cf249a6308d3d8d7bedbb8133d542513d9c4424a3609e81066dece42a7a115279af0155e3596058a4e22f6876cd931f1e4e5ae5800ca96eca88a3c04b789ca1c843fa9730b4c050e269f9f101a48c5c1df7e5770f5a823e1e29dcb47367153a17bff1ec
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414c2f234adf6d0986f254e79e3e89264f7681cdb65efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 6d16916bed6c4e35c76fcf5ba043724e7404bb147d12534057ac512261c1b93b660242f37d3c5d8f2de5725dd5f56d314bf77915c45f0b3df41e23397674cf6e6d05f0c76c3040a8939c9424fb135f6f55947896cda31d6d35e437c95fe8dff0ca47224e81ef016a41bbbc18da4851efd7043ffd61878fba6127153be5c6f4a8
+S = b08db35d788332d2bdeb8e89c371858710b0664e464f9b726c92ffa837387e7ff14a885cc776b1ec4763da1c7120c5da133c3dc01de44c93fae6a9e13c3542f5ac6ea44f3ac9892a5b775a535b4723777a43240af123ef78bb1c1d6788098fd148a764290a559ff2637af485d280bed6e1b289e518aee6cbe842b3feedd158c409d13a5f117c8db853bab5b564e43a06a83f4d2748cd718bdb8fe41f5fcdf9f0104dd8125fddb401e8b5ddcad388007c3c86c0e4502c94e67b0d194002f5464d22ca2ec65af465abbd44bf90e3b578a9884b86728fe22705a9ab24549d4c168eb7b3f1c6f6b07a55c3a8347b392e0eb50ae985a7e3eef4cbfe060692b45c6671597c59947d056b9452b2030529705a6793547d75d67298182087193f608163f3599464ab3ffe82539e202679b84df75ad7effd5985b9e08a88d3977dc978b748a9bece9e08b42b88ec6a766989aa03c1ff73445706035cb50fbf01f89c9855784912dc7b911cadacb0fac987e7f5bab76d9658ff84755c70225a4e42bdc84feb
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 724265b54dd8716ecca57175e3182d40c4ef7a1f0d9e0fc240f095fc75f0fdc64b0a1687246e5f9392b51af10cc7a161e6fcfd9d8081b5e0bdfee4a5b6758eb1b06e34534c51a6ebfe1319a9c0147997084801daf7960835d37d1eceb7fd573589b5e7a22d49ef7ef806972568c95deb121cad5ddba3b1c96bb76a00df50005a
+S = b2f503ef1d4b84ee0abdcf78640f1f82de00b2f5fefd803e1322a3e09e617750884b4d6d7e8aa741c93e9b36dae70647c3fae398161729f2f8962f9985157ff7fd7de42d8ae7579602fec0f91d0350a8bb38fb54234d806f3251eb6ee2a3806e3fa846a7add80f0d2dd2fe9977265f5ada5012f739bd3f06925d7b8ce869851bbd5897b819c71effe7a611b1105e68a3edc5b70cede299548e9116841ff1ee624ce0d8d477a18c723ac05c756084f4e7cbfe851db1e044ea175c8603f90a4ea87421e79565b8ad247c9885a41af0a2d1032f2807b731f574d54b6c82af900b0a1815b4e30513c7033e67a1c78329dff1a4542bf28aa5ea78de037bcbd7a9e0740693f71586d2dde6df39a979dc55335854d656a8a4f123b4414504b1a3f3f0f5e7d12ab700d24b9f34df58eccf2371d9e8429f5f206122b3663f99ba02929e8f46aaf061845f793ba8bc7e4de8621bf2d1df9a1ae2fc130a478437c10d2bbd51207dc07af35c88c5807c92b739d3b5a689250ecf86bf1bcc8e3b5238d2884073
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a050004143ea74de96d5511a9072c9cb0dab7868fc0c87e3d
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = a6185cf668fe6bcd1a872da768424d95f6d52792a0342c580617887948aa03aa0e862562cce09ea44400e5184cf51e61d18841ab1c6e798354c2caec44b2f7af5f78a3f2018cb60cf817029843ab27c81932b3fd2e258e9431ff960299f08623a1d51ccf91687baf40b4ce4ed7cd2e73d7bdc6af5ec13432a6b633e2cece77af
+S = a31dc7740083a5c5b17c2b4549d4ff97405b2de7a5d878ba927fe7cba62de764685a23f65cdfbe9d0ae2060434443f8b18d8032e7d7b952428dab81cd158ea3946d17c28d1bb160e6e8da0be12489206cc1c57670da9277e53ffd10a3a4883796d9389e2a361e335efe34e91d6d12e78f606a7e79fa3afc7640396d72cf34cf39150e7784110ba4c703d34747ce050c0d679ef7b1e72cc9e049e4ec583b9aae258d08560e74ba41d4917d8f41c1d4a3b8f04bb76c99b36f738619e6c3b977f716f1229da7d54287c0209403ceb35e98e77cc37499b7c2127254ddec1826d8ed6fb83ffa13e4727ad2329d6c85df002025b0639399a050bc2ee13ef43d4b5cf25a36cc0c9fa27c2e2523093dc48a2b1f66aab351965866459f6c4bb59827cdef8058311a81713c011f8f77f819c906be90fc9e09b6c5cd8ded0da32a30e756ac1fc26282af539dba2398ab21a254067fa338479714fa3b37fd7d7e6032e6b9e5cd31f23972b1aedc53778ceb8a39d3b2b3337e694be843e35dcfc310b09f560f0
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = f5df0f6986dd3e9cf4c243af92a6a69fba85406eb7944318e2d47ac80ce7d24c1c231ac6f9e507a5ab277bd4bd550631e55dae41e706eb22b682f6c1dc46434d1d194ceb576b91abade9ddbae44ecada0d7c871065cbd99c79a1602e8e431c573fea303e681ae594432ff1cad139fa817c095642fa8c156f74584179e8856454
+S = aa1f614775143e046d4ab4d317f2a69a319e82f91dd4e9e3cde226c5ff87bca2093afefa76890fd8a2cefe38c96aa94dfe9efe7e3975425f77bc6b4b13f2c84e8ee80aa7ebd95683a95ae0255f0923faecce58b02c6dc9ac9336801fd0a768d6df0a0b705d8e1402fb8f769ed32f8cb890be42b86a1035d73f01ff6757bd02a7e99449a5849f0f2d0003ef53773a0b13cc07e53a81a7914892238ef798faad7660f9caea94abc282870714d1e9bf7d29840f0beea5cf4addb6bda8b441db30dd43e207249577db9af55c674cc58ba2cefaf1a4fb03ee766f45dc46aacd12c7cc5508371db63f2b971e6842819a33b3535a1592787bdb0544317f88cfd63e43dcc987472cfbafdaa5923b3737165f979ebfb647d86f6d2a8dd5137484225164b19f063fca9cc72f516b2402983f7e5a643f8cb299870166b04177daeb90ea978e957d5f7a918063253d7144f589019c7691c6198f830b86d9c8a97af6d530d0c1126b377d5f450ee9eebe33a9b135774624f575caa08871c549f2d074552ca2b6
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = e3fc380f53d94344f864766b7f1ca420e59f430ff31d120a080bff5a181c4753f56ddf2ccdff130df46b6d68e4d1d88d83120579a43f0eefcf5159cb451ac0923f7bee4d77d80c98e9c99ef6db12a7671bd6143d8807572bd321539f87187851478e2f1c574a780e5fe6d1bb6bc75bd635533802a75d37e59ce4b37ee7feb8b9
+S = 6556cf98dad966f1c91e0fc492d74f52a7896d1901409047bc630f4b4e97044cb9f142e6560467aab4d65a302d856f72c15332873e0a8b646b3c70bfa8d522c50906c240289741e5e9d11f77a640b7d96707c959d130355fb2a2fd65af4bef7f05ef9496f630f79139d90556a970e1110d12ef10a1b7e74e6dcf7a39ae299ef8649c06d745104ca65b82b52eaa0f00f936525065221a690a65afd7699d93c70405403cc13a72d944dcc0efcd431604aa638515033cfb499207de58a798a22c047d18dc825abead4848c7f521eb1ddb2a10af5fd7bbdf9eca83fea139f6a015b614d7126652a302786850f400c05c2945de31cdbf0ae83c3e39c80a1860d233f17e5925a211b1a35e1e7bd72cc1785f9674f858b43759542809a3d9e241d29a62519424c8215815e0e85bd1374ef99ec64f08b3e84e3a6c04918462098329c97d8522aae23e3d5511d6489a1155774916946e7e0e10979905c5cb603561fb6004dcfc30ad2b6817272be904e928c4951eded095e75a5f7726f255b01a85211bf4
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 167c1cf3b93548a9248cba2d5024da528f9a23bbcdb883a915ec051157f8adf268eaa3e54a4f95f6aea456b2b70dcb81014a0736e2e6b5e5efb1b6f4c2710c75fbd5f7b385aa5d0b1b516ffe0a718a8438e95ba26509473eb1010a335e999ea1d8235e86f2ae6b93737d4f38d1b8e0023c606726de88025e62c347f3b3d92a1b
+S = 674ee4315853c10823b2d0da2e4b13b6125b9ab7ec5458fa09139ae74dd16b83f88a75bbff1b7d70a3d099d12c6a84661dc4097ddf5b569a5f3d1ff4de4b595dfc0a6726d1e6d1962af78a94ed73fd2104fcedafb61097f8753b5e8420e17e284179e7fbd16d3ca50ed0a66c5c2ea1e412f3f758ec18f6fc07e69164f71a8a1d779365a5042f5ab514005937da2b92b5120b62590134888134176f5cafbbb4a98f08c4e2d581e0ad9deb2caa666f36d4ee13e3be6a31861e4609479dcd4796b9064e7164aa7569230baba4fdcda388bff7d2c52645e9d4331c76cd2726eaa7039078fc0f74a47882bc0a47ffbb43e284d6dc4532e94f4bafa5e17d8dd2f108cb2f3b206e06eacd8a901a6e1f7c82ea45959c3de898560678aaa052ea9d9217e97b2a30de1cf6649fccac679f15317423078edf88af05080b679a581be29a76d8cc20ea7d33ec576ae8aef7d58c1b3126f6efa0941434b6dea5c0ffe8f404f1d37cacc3c5e853ad269a18bbc19720cd214eccc813d95ec62a0f083d2d0e66224e
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c20f660487ee230a6692b24f4eab6705e71f3b31197c1b445b5986def
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 2524a5d692240e9c82d0d620a0b7a08c3f71ee679bd78a676174268672363f57e469479b4ae6021036883189fce06e43b82a5777927fee2c404c404fcd024505990f0840a20e0791013add3db8291e92aab7837beb4047533a12d0f7cc21921f4cfd31ee1f02e5c7ecce23635cf97a201e00bb9c2f815c8358ae1ea5f8fcee4c
+S = b7ef6a53edc10ca9d6a16678c2cc38ee3859dfec0ed0012c788c5981fe2a1d04103acb6179c176d9f9003eb86db354fd504107c7921608e131cb3d4642ea87c0be3e91e7e85943e7ba650db959eeee710b0cec5817990de252244e95aafae943b9828f11da0e490d11b5990ca2d3254095f3ffc0defc38e5d9d87e3088a84d002844b8fb7231cc7d69539bcefa4eb345168529a12cbf866a76bc1f46c112b25099f91290222b839ba7167e8bb99a001d139e18a231c6fd5c7ddde5a0799b2885f8d32b77b620fa555d43bcfa1cdb897e53d8786f7fa2a734cf881994fd8b71148a3b96791c18d28fb6e39e9acea7e61a03b3367a1eed28c15ffed710389c6b047ac5cecc30cf4a9b0ac2648204c72ba48a7957e7190e4d34bd8a55e3e488e61cc64f1130d81f5a182d480fe032aa7f7302ab386eac8666c2213b103872564c11ac0e63f1b9a2946f3e185a0815e4ee2aab57a592344afb8568d70979e62077d5256fed2aa02d800ebadd4d9b26d7ec7ef0b3edf89d2fadbeed40f35b54897f49
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 93af2807782787ccbdda1f2d60e56c455c5ef40f152fcfd7f62466ee59427ba2a75b6a6dc0dfae6d9df5a61434ca99219b29f9cf714de44c7af3f06c89b3289fa38f522161cd7470960296033270c8396691679009f49d173b48272648b75b4ccf7569892398e1bdf12a7561237c017505bec8b9a6cd0020824c92825df61b91
+S = c0aff8cf59e543109654e1bd05a2fac0a13782cf26cff6978a07e72b6aa64ab84dba40836ec1504a83a51374e32f09dee79845cda7aa9fb6c75a9bde61616addd9bef949f55d5a638615e3947c64fe8d8a85bb54ef6e71090b7c84812da8d4af8929c1964f27820435a587318c148f9221fdb4b63ce7f43c22a0e840bdfc56ec1205fbc5735158a1a6624869e4ca791d95b2fa01b1e1434709014549f4c0998a0574c6711d1a4295b653317db362f151b371a851535601de3d66d03c24fcce8116c1242e523a074754231f3c70e9e2985a5228021fd6389823a48b5aa2a70febcd61aec23fe98f6a9f305d588289c6e3f2522b6c28a94bdb27bc81b44a39a0b826572ea40a9772b9e3aff50106bd77b2a5ccaa1b901eee1d8ea6e037f7815110fefaf2cba69c55f7035d2771b095ce38d13553798c400e2f7d407fd0b3dcdb38d8592c4edfc5e5cece6aff1be8de3769a3269fc2a99d1ecc98c0ffae39313c1827b81d361074f9d1919829e23e20d0f2e361417b35da1eee8849899ed2f199fe
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041c9cf324cc0a040165d93508d7218c029560c75dc71785fa64343930ecefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 38f06d35930bdafb5aa674262c796b395036f3a54103e9e26a2ebabd2e1c81f42b836f00c0d97032cc0d0b01b9748aa3ba065cda50cab711138f82a7afdd718b2d2b7209745248e30f4275a430f45e31f5a0aaa1eb2feb4ed1f3802c9e96ba5ac5503df7b75da937a9af7ab698e02d0c8b6aa5a1191accc32ac27df5022fa28a
+S = 0ea93bb8e9b4639bc999e044c328e9991b5986dec71937465695d5ede0a28d5f152cd19cee3794ce1391a2cef186a92a789e46f70d7ab5e38d0d02ada5a9bcb558ab77fc06ab08db51d159cd9648a49cdd7239748ca02eea81e3e08758cc4054e279e1a98d77a2cb9ff77649c84e843f02d61b98ab73788da32b8fbd9e7d0338089ff2697341e4fee7cc72b73093e098b361a76eb0d56072b9bd04aeb05eae4c918027dc6f3c12607c504031d54e456af36be5c711b544bcba137fe415e96c25d5931a4524bff801bcd5f771370d42157ab1304c201ab6654dfa4f5f933aef840b74feedf08a3c8d74ca4de6fe562950bb7e5c3d901a3eebe1bfb2c6b6ec24b44535bd0f89b6ba7ff65378a65781ccc5243a9578f74f90f894447c49d240d6e118e92ebfcd8079326174b55291ecf57bf39813df3651f690eb1c5d8056b8bd50cbac145e909138c37a6844a5b624da4be9d13a988a5c43e2b49d11f035a92a098a59071b26231b024c1f6fad1920c2059cb53838215c6be939b2db31ba595ad3
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 49da6ae32f9149781533adb07e035a916ad270052b7ee57f74b931e1b30b4b9ea01ad51b162a935c23e022dc5b4be7bc71254520085513d7c6b94d3aaa230956a0a1ad4d530260f94395bed31734d01334813b198e70b70cbe06c3c1566098de71f65b3f8e2196989edbe95c5bc6fddedc71bab766d6ba678627fd3f5ccade7e
+S = 1273aec2765d853e0dbc6819df05d3c008cf12a14078d0398ad1c833340e8aa656e463f170324879d99e14a10f67e29b5b09b9dbe71e93b298c61db9c47426064dc5a95d250cb06fdd9d3258a6112180a390df3a82aefabbe5c3083e0978725da87104c50d9e831d24ad9545f3c11eade633638589e04685f671e68a6ece18c856521d91d4d74fda95879ee39a45ac139416472c3a5ba6fa17d744745da2a7a5ca1b2d38e813d2058f7fa54a2787e464a9764b11f7421f6fcabbf982f4046b4d4ef7f0e86caf038265c0f1711b2ce4ddcc5a70b8f77337fa219c1068f15f8533d99e9773313159f04f746d629129f03e517280d3c41f304e531cb8ab3e6c5a097700e9f890026274cf9deb9e80836636b3dfb2133d24cbd7c5174e89ac5e28dc2523b13b4e1031913e172eca410c3ac3cac74734b45f8448a531aca430f0d00d3bfbaede84d9c4220ea88017edea356d19e30678ea5f82ea7537192f10489ff50e40eed9f4f78075a37613df24d5da59fd075f1a45cc9d7a61a2ef8274c0e7ff
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = a455b7d1b3b32ef7daa94505fe97b16726745409dfadbfc9df30f52ce7c3714fee9b6b217b2a58d05338b0815435f344a1ceee47ffbe3b4a7fe707525ea117a229520de7243fe8b3eda1cb2c5dfcff06afac3aaee4c022c8650c0ddceb7a0b4c9ca1268a7799e887f10d1e6fe091dc939936c1a7555c7c2ddac88f3157f75337
+S = b92a17bc07f74204ac547672fd12d01df6888ed332d1453aa423e504c11c4828e500edb7ccf8071f1f98c4b68a7fdbe665a3b82fec5acbde24a0be40bace89bcb59d4f9b83323e6f3cd0656cf9334974b02d437155d6d37a02de832a8356a88f83cce253b4bce850d9c5e00e89a6bfe1ef7215d64b68a259b8f25fab901f5e6f9f0a8b508c554f2b1162ba358fa5270c6ded1e36af3f47c3558523eb1c3c7d6373e4679324481300e8af1737ee62b840001659678987017d2212c4387dd16105dd81f77b40357f607a7d5bd6ce07f7ee5d7ac4cd6d0df5136751d438000b26e4d36585ccb743102fadb674251a870396a3c0c91f6df33af415c196f7de0746d2060b28b456bad9b0c81d22a58f2e9ce06371b5d40a8eb1d0fb98a1610fb734e9fdd48fc553b08dc13dab29328cc3ba552557e2bc4c245c247cc7549a03bd2b616c01e98b04ea835d0f02c6d13939f62264d28aeadce370df07e722057254aa312f0abcfd306431d880330fed7d76337f58eca8a24bf3860a8c758a6df39d95e9
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = d262295e4f40d1ddaecf5fcd56af7b80625a4cd83c64a3ad6d02766fb3ca910d54b98815b37af01c21e5ce60f5c750acdfe1bb7c7933a5621f7a64a801f7c637767203b7947feff8fd007491fbeb40c7d04dbbb0478f3c988ff87ca349744bb4e094818e19d53839eb2538a890a3b398dca733bbce02d0166587a6a7b4ca864c
+S = b27d86aba157581c706913aefc77e7ac3c9d4946c646a6f7ff78d4c1c19d0488637c010dff274cedf37014fe1c89d29018daab58b5aada55fbc35cc973290d3f4a7e7c61f78fb3216793d087adbcda38d963fea102b4240a09cdd433086248173f201171ae10014b0c785b5c374c0fc2a38e021f98d78954aefe53244d01cff67b7991ba28dbb1127f21ebba54440d31f5ab3bfa6be1b7d6696445e47f071232be25b08da70ac8ec00603910f9706d6f3692de55d1e646cc7c34a4887cd692e69db28e00a5de8c8d2a618e351f7714c59ebc419231e36d6debba2d3a054ecfb9bf6268e6507aa96823acd635f6d31b6d716ae10425c9661a0a8b7b8797d2d90d27336faa572a13b33dffb81918b42c70c28f0ae88ffc923120cc50ee8f5d9025f71936b606bf44b8d1f26dce76b1b13f2b6c3c5903407e846fce2dc7e3d7fbfd00693e4c25dd96ede4e29473d8edb7532b729010df0aa73d81386c470af3326fb3bdbae500965c0bcc7697e92f8cffc14ea29e5021b56d4f78a668c72a57bf86
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = c9e861253ff04d978781a7a45099445db4fbacba1c821e905eb6d4bd299d87a5a3d436e350dd243836bb20c73fbc0885de9790ebf5b640eef7d5bc304acc4878efa98b606402934dc98a1aa443e1083b9eb1390e36f67f34179deb11635148ccf492e9034307a5be88151fa223b04b683b712d8da5e9e44a0736e8c63dd3908b
+S = af1a58738c5900de8d3be297fcd89458a2c11b90532dbf31acb6a4bb1ef2141e866637bd59e7af286f396bffa1fb46e13c2ddf0591df51a8ec29691c03d734ba37727421806cca1650cf172cbca3c60876992af88037e6e43902eca5c2c91ba7cf8a408adcb5545bb4151f05a31db4bfb17978aaba5b5bc626c07880f52c47f2f53d60b5197f4374695ded18f18dea635940740a3c5aee8caa9f01ce9fb02ee9bb66743fab75e63e2233089302044085c5e0ddb723aa142e0ba9f30abeb47782655d980dd7869caf0ca65b25958395dbff5fbac082141bc6cec4f032c60e973e0a6b1421f5126b5ecaf92f4873077dcca2d90b492ecfecb1fd76512ad2726f9c036206bc34deab19dd39182b8616eda9f97745f2e09432ae55ddd6ec683bd366e45668dffad941e7458e01afda6e3a232fb715799975cd9d81130d73f834300f2657112d57d661ea7705e912854676e50c43ace1093ba5bf579627e97e2539d6b0fe53741541487f89c2fac52fc97dd4dfe0b58c9637cbbd84011a80adeb3789
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420bd0a68c45ca3504eff3fd99a411e4930d50450c1dfaf869af04bbec14d10a9c0
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = b44a3b7de7c8b57126fa95ae13853b28a221ce78d84d2330d242e06b0825e1a8d380dad82df33eb5b82760560304d90008242940f987a1363c888034b40f5c884209c3958b152329fc80e70a0c74e3d2c16cf2fd76ebdd41db6e7f1e3d9f27b508cb3edd8a962a74f9ee71f3b83d2245d6e371dad8e3a1f7b8dc27502d3c0cd8
+S = 7f0b8969669053c26cb0051e0c182fa688375ed6afdd39f7982d88bdf8d422e9c9ce4ab5d1f63a18db785031d17a3286d7cc1349d1ebfd764522cab0962fcb1e071394d00b4595231e8fb7db6d10e659ce8158ebe78e7ea60818d0276a2645cf2dea02d12e9447652259dd12a93936cf2cc0259d03fac70ccf47c99dd8e0b5cc9f90916a961e9b16f9e80b51dfdb38a6efefdb5e2dbd7359a292b89d8aed8868b7e9fc444a262a04a331894a57ef0eb2be8ecf79c6481fa8bee709bbfe6cdcebf04325e98ea156e82a4cb87afd1d69eca37f4dca02c319c3f83f65cb12aad441f8cb92e48ae789626b3662158148a61d8bad4b265df2fdb03730b947f5e542d9ef319e271fa27e598d39c9e6b645b610f96836ddc5523263a98f901f9b47e3046fe324702732a62206fcaf7373df7d987d236574b8b66bff55518ee403ed9e9763e366c26bf3ae47c8f1be461bcc6dedf549b3ea7d5649b5d7bbcbcbbbbeeda04218b861044f3115b684cd82a71be509345ffef5d5326071c4c63d119e86ff38
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420e3b41f283a3ef951ad52a3dd58c46db1518442328f512485699894018fa1ab54efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 0d0547eee5ac01f37f29f03aadcfa560adbd5b02b5182d23cf9787cde745dbfb228295b7724b508068bc4aee49d3159963779036a1b916035e59f566778c22d0a4fc2be808116ce6066f863c57c00d7c59b38176aa4480a0f63f39bc0dff24b4397cf1c9ce85beec02498c6cff1cf4d23778160af842d3c3404f3c17d227496f
+S = 8b3380702deaf0e22ef08ca6c3c9e68616de1359a1cfd5f03968148a837f11f15474046c6434aa2a69005855ca945556c04ec3b57daccb2605683474eeae4fffeb19c221ee5c61b54b0914dc0ae7253d72e6d73b669f52651ff2d25e513e565d3648e6d5eeee63891ace75b924a2143dda487d8076174784165b105663719273ea6b42209ec456bf1f433b117e02e6a5bb35e285618cabebf49a8fbdf046b05bbd37020dece2afd1f6c9bd2fc804ba09bdb0d8aa7af0de45b7ff616d051106f6727415a460a62983817e373474666dcc8260a3ebfd59341f01990e6d8b7d15092c3d7dedc2d4190d75374d138bb414610834d48c9bc23c43d1ea96c7e9294a2d803c26a427e4a2b5f86f19bc7d10da9aaee219291c94d7a3052211f6c5b739168e544747b8090705a63671df1ba7a82d8cc5e76b5475acae66455fe377cf52156549d7431191573f60ffdd24d6640610f4515e3801a526d49fefc2d1b59456e3337485cab9955afada0ad5e33deba6944d98b24c24731acc54b78ea1cd2808fa
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 9802b7acc01de6de29215e2878ea1ddec20fefe95963e56ce5c203a7b60a391b586795ee68d4b692a7de84a24dab1e0ca03c1475c4efd7d9d5486d7233f069dc1dfe1b768276040b130f8cb29d3af8f2965f962af66a3a304886ee390028e6f90f50b20bb50cb792963de021119d91d8cd01ddd094dcf8ba6505efc2c4ba96ba
+S = 99e39af2014f011fbb413ec25a428af8ee4bf6f2adb3fd20964d551ad8355c46cdfe35c955cff611d299f533852288ad20b901d80e048ca80eb3cacd83e638e15953413e3018076e91b1064b2c0d615c8bd6b9098f7e3b6da919470636135b926c97124e943e987355c6d71d683136c8fa9698f15c0ed3abf9ab7f03f5e565f1f1b1b056d7d1ecbbd1d7afc5a45bce19984c8ff9a92437d832f89f0cfc5700d18482c4d63376fdbb851ba2a1f272df06718faaba2e9e1c8ee1bd3a3aca58a02aad3437f89fbfbea5f12b8ebc336b8dc942058c80e099c60ed6ca6ce128faec8343aede16c44ea97e1ac1073e24f5499772b8abdad9c8c33922bcdac1068715c74f4822b4e9109a8020270997db56299052f14132a1d7b19820e380ea74a68236de72be5d33f4e89c5fed4ca643f6ed7a3f505aad27a22b6ff694597c883896fffba2ef4fe81cf44cfe342ed6fa127cf31c58a16a5a35919cf2cc3adb47c6c84f660bd9e2dcc4b8b29beaef329affd4b5cff2c59cebaf3648624485c4cf94e9ec
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430825058944465183ce7f88365fe96cbadd70cebade9f1469771f0a1bb5ef6e86c4e3e35d2a34393aad10183ead0436783efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = b438d4fd3a46058f4eecae06d9bf1d43c54eb5ebb504446bf350903aa902335e55f9a93277fba8668ce4af474003e241e0c115a20e8327a0b8d2919e4bba3eab236f9e4c4737f67b5383faefb55f9d9e1c0d28812eed89977aa1ee2cad6d935b08e4d8d211c197d58913b4869f9df663637c15107d0a14571f03d06d38e6da76
+S = efe705f492c2f05595143b7d2fede01de8d4ed8aa6730d5db7540d9353bdce15cad57eef7e66e98a0fc3d34e223be094c5f60dedb8c89f5c3e4f6b10f5d41415e098741bcd4324558655b215217582daebfd44d2154748a707d2219f68a1e9d97a75900329dfc0d7a28b1929775bd37fb66524945b6b86635dba4f2e7a95da17301a1522effe0728edf148e7007810ad509d8d541e6520b83247052e9e79a84746f11f469eb4db1446f5dce3519f09d8b4f154b0f3c403d23a37e89aa68683027b76fcbdf373496216aeda698b2fb8785e364bf2bd2449277c0d8420ceb2c157f8663a35c02f1c4a4aa86c7753ed755e60c022a4bb3106da295f3a2a72f2c861c619b8726f1749b9bae639589b72e9e34eb9176608f2a38daee1329de2f28291216b8c77a7409eb5c1d7e351e906f1f25a26c6df4abf3038658f7cdcfa3e1fd611efb4cc6c5167c4f76e2100d02612e12d2e696c80ce977e7a150e477ae0b67af577a62a6b57e6bfb9ce19f56979008076c73f018e5479de5c69bf1ebf5aca53
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = fc06f66ce9cb46deaf65f79666dcfa90b09d1e2fecd7e2caac268767696f6ac6760b91a233278433836a5ef780d923b26df854b4eb32c15a707b9fd7f634da34f04fad9682b36fc0f1e2b0d859d9846e9e381fbaa4a2a225c367350c756056c0521b70d13f38b08ce21314c259a4c5cb2ba3a6cb7eef2d348b30728c50bb8571
+S = 6106401f71a67b9b68fedb23595f45492fc7eec4557a00a5638aae54d3854dbd87d2f66eb94cea8c02f466a85983a37fd202ccad8892eee14e3301fc132c530b36b31383739ed7a51433e90cb7ccf1c17a0a512d249e70a3d51b7dda16680946872856e5901c726d3bf2af49fc264c3c6a373d9135e802a8ca37ba891c9e13c21dea83ddd6c55c25867872e18c0a726d5fe6dd3d6ddddfa0cff7246a63dd38cbd738945afbb3be72c55cc2ef38f56d596619970312d93a9322098601193d1dd537e1041b46e8ab5d67b40a069b4153d365742a32ff81defb4fd00782695b81b124959d33c29e88a1d911c4da17dc32d41c1b5f1836ae1654d56feb9a55a488a2a97a92ddfd9c754713309f661739cb2baef671bf41a3e74452690e0131bd3a3675316d296d696b0f07a50516897043a5b2f090bbb618d822245f5fa5aa7125551aa988ffb289e8804bd5149cc8ff372496a5071ae7f8583a8755effea0c6599116ae5b8a3f94ef2f4e6d440c9304d6a091ebf14fcd8700ad5367a21e6e8105ed
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = c2fd970b5b17cd1a58dc8423f1354f7feb5fc86a609c7b59c229ff8e1d6f66e99c7dd8014fb67a732bc7947a53ddf4c096148d743832649df595adae436a305ad820f2a96c1c124cc0aff12edf45954ba3df50c57cc39c346d714a3e57dadc697acd2f2c39b25d4c1d7ae1661dd6fcc71da75884b4b6ecc832a61f68e22730bd
+S = 861383c21c18f931fc4fb352d846e725e39cc117c4324952344cd007b6a00ccf08fc79048545fab5c30fb356460d5af25a63f83871dea84d464ce4179cbe5e6fd09a384c45ad046101a9460238eb3f445e8911970cb9c43d096f70b78f3434cca05cbf8ee861f6bb6cee9e123a24cbf6ebc5021d3a9a55c7ff08c6bb274a7736f34fa7c04029c246f2c70751e51a4607484ec87e816a3a5c92c06a10f512709fc4365a7c80941109b1cba4dd7ee79d4c3f851a32763807425e5b7583d49e97f337f270e6387f99dd21d62c9db52406d3376a5e549782625813634a8fd237e7ac477355f4be7e05e2a9c3cde9ede554026ffe1ac3e8f545a4d49ad39c2aee4b52c45440983f25c276ed58ea5fac719c5332655113dd768d93311cb6dbff54357f40c23b4bb9c20c7bf0525150e71e17e486eaec90d2263c9758447bc02739a14cb7c3e60cf376b9326a861951d6d38ee291e59219757a9de264cfdbd4b4601b8413161b927daff25504e0361f6669af8cea75f35969c910c3c5e1890597931164
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = cf28960fc5ef7fd91e051ca12516ba961ce953d48492fb3598e97a6a1b3a3b4b533e656c564a47f184c7f9a355e240435584b31e6c851ce1631d21afa49b24714159676d38ef741bf6a7bc3319317e0b7a98ea206b7587f23d63d21606b22886a060e53bf544cefe7a8dac7bfa6b3a97950c410308ca02112fa3d4c7c8e90e33
+S = defe54ece1df4a9e2f9b2ec712b2047be979113674458c3e1409777a8c568bf43b4455fd4197ab42fc514e3595cec0d46f3302cf556889820e1c9cfd38c642ea09adefa815727b6c06b2a194e095f2696e35f3611c19129a86bf60b11799b6587bef89082a631cbea67fc4d77c7dc998afb8caae59e7a63a5792cbaddfad6e3bf8a0d0fee650b7a9cd502211dac3743642075a2a563ee20c05393992c776869a6eb4a206de21e72ec27be193537a32dfa65831bd13c66f6aeb2bcb6239ef31b2d7e8deb309be4f639c7ef9d3e6147e15a8a9dbace13315a3267bc4ad07ce02575a8b279b37646b871b33ddce57a8170c422474c2aa5bfd5323288753628562f0afc715576c027f7f125793dbbfce3fbaf79fc032bcd9214983fddf1d3a083819399c107e2913de535dfbfb267cd0e0602d6836a902c6589bd1f35dc07146c166d26592d8d52fca9a82340c0da7303602531f8144aa1f704e66380e07fe3c54e13b1361a427531a399616b4ce74ee9633347dd29112e180c5ed263c0153f3500a
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d0609608648016503040202050004307d7ca11cef0aa9200c55b78df8c91c41266ce955d1fb2622cd36ec797f3ddf70eff54c77a2904cfcb282cce545a31094
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 835eab9bf266d49ac4c672c5765511461a3261dd04ab8bddc75ec577609e253ab019b2db30b7c132e0c57f868052ca0a03d945a74121abfcec6263a4c5a955b70f7dfd9344c3bddc08df78c15b1c5c81124eff2e88b6aeb29125020faf64b3eb89d4b14b9852719f245d85ff6f7b70b430d8b8fa42313d049ef0c8418799e7de
+S = 7f96dcefcdd212f01c585dc3bdb38f3168eed84c77eba3d9c5e052cf84fb059974ea282c5d5a4773e13f4d23206c3ef731dbada06ccb827a75c4002a267554f2d2290e2cc23791f8db52aaffc7e2af981f9ea55d8eeb9abcaf379cc47dfa54d28b59686e737e2e4c3a4c9039ddfe637dff0f1ae77ad9fbab078ab9a81259785880890fbb32c70301877b6f53591862f45463bc7c25da257b8fc798f7d3d115d6a7b2228543b81e768516d8f29f645165c1378623c3e32dc6ca08c452665038db2ef5ee432857e60eec20c6ba75981833cb78c8cbd18bc3243d4959ed8ea4e5cc3102e1180530fde85e837188e029717a6c9444265d5bf297b44bcce7367e3579f09928e97257f48f935a869b72c53be1d3eab08dd10cbff54bb099d2e9a2d3ea9acaadd2c2e7c0ab89f58d265941eae9b1bd31d544c4baa8132859869284154b7f9b99fc98cecf104473437cd6960a768f044a655034403896cafa00fd89b9968097d2cfc90215fb1b6e068c0cd6224aa5f73013e1cddedfa80d3dbdc0bde0b7
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d06096086480165030402030500044092c353394e0845afea273cc4747df99a1d7a0474ab8902f073a0c432a27adbc8398de33e7d5b73c3cb4df25e6067981f237b11f009d9c1e547af65322d32905d
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 62440e53c9081680b721630cf3071ed102fe0ccef99906c98f7ca93876654e62ec6e3cc28d8c1dac6b5caf33601fbc49a3024c289aa419f1efd24393e69545efee6e283a76e0f7a2012f72347d6806fdd0a1fd6fb582f307c604892dd9795d5c90cd39822c0b8aaaa22214d8f1eae534b262876bf13c7a533b9be1cef81b7cf0
+S = 646d7a66aea8b4a22f75881e6647ba0f207bd5cd15e019468138fd126e1c7f660a97aa55634646cd8e5e584b6bc29a4cd213cf222657ff6526b7e0ecfaf56c0a90ec4f17a297b0f8523bdf39cc612757867272409c65e8b2eb463cb134560d021f60a81ff4eb08aa97cbd6c07cc3b32422442724029be186995c2694ee4def6009a7a1a8b3c9eea48d634ab3b84c0c9566ede4eddcc5e59338ba5aa304502c637f9ecd0b707e841d0b7befddef4fe0875809fe386122882ab02e9d06af3b9953d8416cee296decddc3b2e36329434f567d57330c418624c5a70cf7611552fc2fb420af0ab0ea2c6ca4b19a0854e6db10662a7fdaea3c015e53524617cc29afb9cfa9065e1065d95d288f395402667caf80d7b4a3a91f5b681ff10518e5c01ddf0f20c359ebcce526091164d5718cb49b9a42bbb57361865384e8e2e162abd7629b1fd242892d5164c012dc07650c70cee79a2ccd13f424b574eb1f6cef662cde18302038bad6e100a4e7b949b9f1a87de5a2d6352ab830be1138d9b83c4f8992
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = 7c38bdb32ddcea204a99b5f953ff3d6e0adbefcdd40804f661884a0f8fd328798c6fdc023bc1085cda236dcee137f6292d7af8fe5d1cb80e7d0f2e02e25e085c54c0f2ae736d15095330ddb96abd002fac46bc3ff449608ca6ac0d40920bbe001c51861f9a851911fee78e23b53c636acf66c2f95f370257258771316a84514b
+S = 0d07f7c0cbe4a84df3fc088750c9c503ecdba6c37a72ffb15a2da05b5c99740c894427cbcd6cb2c8ee70f35175e70f226c466761356e07009ca88752ae2cff5d7b2e7f2da77a36b68de59db7f5182abe88cb95b52d766d721b5fec504f6aa7b9ceaa9dca1241a5819d4d48ede38c045d625442b27b8384dab964616885cbfca944a747f024032da7b3a3fce0b02254e08c8b9e48646407e69aa317df5706888fc13f091602e1affc23f17cd50ef4275e321a102c2b066975ee8a0dd3111cb0e88037ba98ba477ec67737024ae92edcd7d944bfe2863336a59026052bbf2280d542db1cc70f06a9509805db6651f795b0b4d74f94fbb06d2d4149321f9334f5fdba395cd852e46ff2ffecd063a96ce5d2d5b15cc075c243b30be7a260fcd6891ee3063fe3898037c79309fa043fe210974a1ed96c14bd0f0db1055f710367e55d702ef3a9bdb9215368407312dd415f420bf0a90f67c53c9474219f36adee08220b0798d14c455e57ee8ee47f2b8c7eaf8d5f8474a9d2f51d49a785ed4626407c
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440a780cdcf06d5af7e658c9a0afab551db2fe1c5d86b54dfab86d5c10acffe37c4c8ef7b65dc13a26c2330ad19d34f1065d99ce4376e6b9886cf30792e9430de25efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = df8787cd9718e6bde708b9998cad4e91c7d58afc60b719efeb2ac80f4a152ea3732792ee74c809bbb44fdf397b753809b409f796f2e6dfa5b223f82de08935689c4a532a3def047296934d3e794f2da47af57f1ff501212753cc5604880369e3e058942afc771f09173ccc518f23738aa000ea4072f0279d568fa93d4c6b143d
+S = 8407b86a4d3715092fcb38c7d55a528182cd6cd94186a86cc654bec9be3d472ba908d5288c1393619f1a4ea1322ae01d47f321a414d0cb1e00fa37c71364319b2e3f6935f00f0b5518806e8c21504b2784f14c739d186df08091139a911d7c8612b4ec15f17ea9f069898f4f820c9b8aeb5ea34aad293637c532c47b9a258d633614afb0cacc5ca475fd4d3e24fd25809df22f14c20289a7808806cacce46eba40d33f3392e72ce6316ce02866955ffe0558510b26c303c37c773f387d93739b77e053d896f078d0487cc4085712e2e5b42a6031e3d01808e94b8219304a6756233dbab0a2f133d088e67a2cd4392f4d688bf4f4ac4ee9a3a099f7389c5d8ac5f09f55cd831cee52306727581792455ff2fba50592a7b2b686fe4e7444866a2ff69cdd68895f84a1f9864b7f36c6ae89853adc517fe8b9a8fdfdc78ba03f91dc582dea4fd387858ff90dbcf9cf3878632b5b8448e19a797485ad4bb9d2c28b1e7ac717ffd4639617d4d4ebd44a556561fbef00e66b99c5ada41bfccab314aa06
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = a24b2fc765c9953c545043a7ee2edf6c1887925c6f5301d9dba67f3a67348071501451ea5bc407b76c6eb6eb5569e343ec033b0c607e8540cd58d5f30dd002edd2a55b99f121961e015609cb25a81db8268bffaac58e98384f99c02c7172ae2c4e86b39acfe729b83a91a61007f17513efa84600458c240789efa8af3b256c75
+S = 960d6a156414272675d2c09a340d9e053e96e8ba3737ebb8a11d4829ec9287e6997594549cfe6e7f60018074a90d1e89272672f4a464d969ddf7b634a34c36d15b16c542911ddc2805bde86b5716b8c8e9e2dd81133ae4d70469803dda409e8e8f6c0ae0785652528c02f49732c4d2dd6a33bdf93c17ce851e8d3d7ded4636d63f34f4fb2e43531bc61d2dce3f60cf2e521cd5cd7a5f19c35fb0bad328975676fd7958bdc7a957d0c1ea3a30f9141a39b67e101c9e9832cfa63b4b09568d5d13f50ad24af42d4fa9b6a0c3fd95be4a4d7efbe2a89fb7d675054fd5630c120e48af7b7caee23fe5ba2dfeeadb31aca63fcc729e4cb352315cd06f8e62e9b727b9a8b8ee179c69afd09b4d5cf5a8ddb281607374a526d462d40ed43e9197d871485fe84f8b07ae7ff7bb411d128b9a63cde123945201873f5f257ebee48b0bd68c3486352530819f0b01330217e4acf76e43f676e33bc803cd11cca82d7d0cc0e7c14b58c65300a877b443bef4e75d3ae079e13b4719d2993dcd3f90d234956b99
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 04c4f6f1fab0aceabd3acb55e65cde8e827e671e60339af201352d1c2c1677758dd2b42e54e8f7cca6c1e6038e47b7603086561db3aeb25d73e7bfc8a5ca27042df99119d7f5ade9b8d3a03ebde5783e915334d460cd1a7dad1bd0285b454150248ceeb366dcbcca68a14e7cf660dec0280f59f27ef0334ff4eb5e2e104fa6f7d3a13f312740a3ba0afe61dcc5338b1c3256d81b7a722c2453edd8f5314e30ebaab9fb5ff157f8b37e1c4245d72d82f0c53532c39dc891b4342682f1c9a8434b3cdc5da460b174c948fa20fa960e53735f4c9bb7ee77ae0db7a9d0082bf3b2b5d80ccff914256809abc88c697d3ce0346455be8cde06d5920f74fe841d94bed59dce7f2b96e5d708432a56ac6409563c93a3a8ffe3c1cf9daebb9bb77405b551b13a40b253a819a3aa0164cda1979bb859c2f63da926cbaf3701e30efbe721ffaaa3317e4233d51628427679cb0c46556ff2cd4d6f3fb1a647695edd7601378daf8b27b7f0b3836586b9fb1d30666c06f494d0f62ca96b7bf0f6bce76395a009
+Msg = d8b0d39a21a7b7d11541c35ba83329b6320896e86f165a13cab1c94adb9ee1a32eca2d8d463ce864e14966437e07b01a1d046f0046370bca4c3613dcd3aae03f900075f45062aa883ce68ae95b05f978584e9a5f865bef252105c280d7d4c46a86b9757648004365ad80f6f447154bf96c50dfae376c4f4dd0849edded04d74b
+S = 2b5652f5be8741b03959eb713e46299a62ed69bc11c1e774c3683af9494e7bb8e51bc4e4d8de1e65fabcf1b4995ff065612fb5cd1812ac7a2c1a0aca8d76c66a3dbea40f426d55a6d60572ae28d3444f059ac714b79e9cb1b9bf443315b85e872a4e20fc69ea1b89c01398b1dd528de6410b48c141b1f7e70ac888393b81b20a8fd6add6ce8a423f4f8e57c6860cdac522349b9215e0c1b25c78a7d94852cdadd5e3f0a4baf2975b60a17cb0e3b9c79060b4ea0eaa153e1500cc05c283ac300e3da7b91aecbb10a50e86a1ed74120a0770d0608893fe6eadee193a20d920291c71df799e620aae96b263f4567962fcfaab4caaa4f06d9d0052a5e2ed8c2f62328a973e2f39568507f6445c7e883e81858df862804c419e3ee5c6bab1832521e841da32bac64a4d89400a2f7d447796f441d3784df53187305fab96ea4faef0cb1229cabdb8cf07c9177b8ebd977c4ed6f260a9b9e97d5d4918cb0370e71ca008db73913f2d519b99b376575a808761dd144d74fd8a7b68f38d5021f8b0533e41
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+n = cf92efc93d89c560e4cff3e81fb72672bf010ae82335c342ed80c0eace8fd0333470dfe2d327f9ebe0ede4f39b0260144d1ec783dffda1f883c0a41cd21e9244d1ab2e4869d765c7e1506e5c1be03db067be54e887daaa13e0d5122e872373891a0480c56d8ced157d316a8ec314bb9f15fa49c0ffc0d78f913ec2dcf354bcfdae2bc031febc69c4fe9c51c05dcec9c1d3004dc8a9c62234d91e4dbd5f9455d94814bd6feef8697efdd9c93af4a9b1ca2e9023109905242eb82977bb4866a81220f8232558af67296b34a19b818e5c07ba53b6e4b270ccf67cc7149c79bf875fff248f4f6f86fa4e9a10dfc162b4c4accbd5f76e4afc89c5339a35f960c7e5d156058bde8c9a49aceb5fea67a09325348a8d573e304e9d133f77913c785e5725d615432d6a258dd4038011a7e19369de19878e945e9d4191148550bdbe5bc22aab57703dc880c3bc08c2df1327ebbf5bb9c2e75082e998dc48685511958c4e7b895dd6be533ffe84d5aee6511480e6547b89144136b8aa41c6942c00f5ed42b7
+
+p = ea7777733c9695e5bfc71a4de384aa8d9556b620f13d50a4b3523d95efab4c5c037fe788c98ae85b11b3ae884eed6f3b8f5bcf5ab1b7b20ad3f44f760b2287cc57937487d73c44f4395d48ef746548eeb9101a42a6d27299be78fcc6160da8c550fa46f9cd7252b91f0d110bbdb3ddaffbbcbc60395538565a266b0f78325a4fd5fe846615f5bab1ab0b306392a1d5853da8e03cd00aab4b9045c5d898594373cfe55654169f1c7eb22dc87c7497db4a729b27ab95cccbc4f44bb8a51c0bbba7
+
+q = e2a332843df5531bcd8a06e30e3cd414e9a201b2e27b610f944f6d915a5396b5508eda547a3a9425426d988428f87f71b58f40dcb02b012095ad2ccd43c4c4aaf510fafa7388fbff8a190dbdb98fda002db90ba0f0c819045df960e5d7747654ba73baff92a630b08bd78c1629ca8cc839678b87081a54c3d27b34617d2a53bc87fd43ea3e5eda402fee3d18e06f3ed1c2e0e81861e95766de7aceca9fb003e945f8bd43de9f1edc154241f926e5c761109fa4e9cb359ac778f0c6f748fae271
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = b04cbe36549d4a58dd6ecf23afa174b2c45b9f664d14b8939cea3178403bc3757272fa78b021f3b9a75165a75616de2171664fea032acb5758968c4b1ab63765ba4a607811d4513c48ef0743f5e27e2e86752f20e304d6734fd178aa8f9ea5a74f7cfb1fc1deeb4a87f1c0dfd330dc3fcd3345f035c7614e4944fe7de91b95a2
+S = a4d1579f4732ce97ffaf6852183ec36900945fd9283be8bc50a1dcf81e8c4f277d5aacec934a5fb6951f97efb5636986e06ba302e964d118cedb83fb6a308772dff6d77080ad390ea8e8f401f5e2ab4feffa25559e699e49ce08004b15c49a7915f28099aeebfcbb3d22426a51caa71097fc5fbccf0cef1610c17cfe76587cea2f6a04cb7893394a736fe2d9b4b72093c5109b086b6f2301b7dc7bbab0cde72828407175946cc275d17da0fc63da6159492d70a341613971926be6623b262df63f1b9c9e9917622f365ecae401123baf3e33c2dc04555804e2b6b3dc14ca263121a510ee44c9a4602c005956f1d41e0b6c68ad78200fef0ccaf8ed668239e196c55e11fa57ce96bf8457baa139db776a43b98951b500850170bb57ec17cf796bfa73799d48b24da7fc85f828a6c1287459735b34148ccf84de1379bd2c13b8cff140ce6f8140b8cb8326374def23122b1fe8f015d6b62be5d99a04e62c88e3f611414ccca66193fa31a51cbe9c88d85c9b3bf6802ae24f4f4263a7b92251a82c
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = feb972fee487cdd8d18f8a681042624f51dfa8639f96dcf693ee7e5cc76420a78e54bfb5e21d536d9e81a545ee4a610703336cd60b05776c6001d5a5ff7e89413dd3a4e5b577ce648567223dbac83f6508ce9b46bfdc1b07faede10e193266c372fcc89744dd6546ec0aa8585c0423eec878debba263ef51c9794b9efec8dcb6
+S = 879feb8b92579291f651e8b476d5414e46ebfba0c85b4907a7479d5327c6f582356ac2fd6dd59414b9df5a465a24cefdc39f19c6e814545745710c9098d15385c7823996cb6509c20e359dba1fa6bfd5e22b41aae1a8de26aff1c26427033f6b3d7f4f8c28a3e398c52c8e5221785f4926b9230eefa264b1684d598310a6e09919409e34a693f3c508aae0d861867fa680f0712a1b7019c850b00216ad194e80357a06a995c9da2bbd9f2189f939b228e5487ac83318def7dbe3752c656653517e475764b375f54a26f848e697aece0acba9cc3b722d37fbcfecb40b5a2b7adde54f02f9fa0cf3b2769ed2d4f81879822e01a289cb9b632e15a9ea45e09e962ee27964992f3a406ac9c72d3d0f97563e8296df97d7ca6383e6643d0b499896768846023f901ee0397b229ccdb706701ad048a7d7f17c52b46fd9288c4a6f5d47c0fd6fb55ff74299ef8b3e1b4c2d72af4c24876b6f68bf7ec74359ffff8461f9a9893c9157e0f022e0453dbb87515d71d64178044048c6e161e6730e23e79973
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414da0d47de632ee4adb50d8031bed0027c846d752b
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 08511714a11c3770946e03091a2826e5efaec9a10f9870c0bdab1e42ca07c07814a1c8184df4198dfef42390cb444ffcf8a89dde2cbd8bcc75e83a798d8ccc865c80109abdc061b48562cbc0c2cc706940252a2f520972b9ce81816c5a32b43ce6d435c27ae6d88f32a043c1872a52d4cf0bbaba07e4ec2dd15e3c44b9614244
+S = 136b4e04197fdc938eff67044168e7dc31ff57b7885d9b41df0d3efd5251a5f91e641b73cfc7732ed326519773c6cc77648f2db4ccd056d52f7314e3f3009eed7f2120155a3566a307cf268adb6c004d435957370dfe06570d626c75db422915e34aa53707ab99998c6d8c0978c0dff28585f628a5077873465b6372bc24a9374fc6edbfbb8cf8833e51cd0cd9df4d3edf0a59a531811599666a2617cea298476300de1fe3e12e45a861f28e66982ef0dd41674276779a92ff9307eeae1159e2526641cd18eab80b43a83deacb075e60864804d9da39eb1cedab591906d4b428af9ae9451c06e6a3b90fb3999808a93c883ac59f80b4d1e3a32a824d1affbfe6332c7527745bf8272ca22bdd508822a655e0e4346343233e1068bdbb866eb512bc47abdd8ac777a2b93e12809e8576b898f97a341621a1fed89db77449b590344e8147d0e81beaad44f74abfef11181c6ec161e96045ee3d0f7dc96c53c6baf7dbc385dbce0d6a054970987b392db1f237778dfb667ae9a4f7133c3d49e78e30
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 5f474c3407a08ec87ce50ba52183d2b605d61768ace41d03134c593aee79d401341bd19eddd8b003eb3e125ba7fd3ee32d53c3fb2ac75f7de51a204d7c7bc93170fa77e3643f8465227cac95dfa06e01c0ceb5fc9d0db8f204411ff8815a67a71ccb872b243dd4972b85227b52d42cb9c72e36948b1ef00a79a79e64847d760b
+S = 65e8cec81b96a92cabcd2acf178afd01ea7ac429634804dab05faca839e1dead2387a4a4c702863bd0522c3a6847960f604bceaa5b56cc78f1ccc535e9c387c70f929bdfb564da2c4f8653b74065affa5c754ad6ffb1be0e02918b1e066f14e5abf499b75d176106ac67b6d2ea954eee902afc8816e5c9b143a6820c4ee4c8ab76fc20442bde40a0dcca8f64de6955df646e3790074ae0d11501242d6499022eb9597eb39ae68f52152f71e5b1500ccdf46dc8909dbae8ac5869d21ef30029b0bb3881df988161b7dd3f80d9f0a9631ec6e95a33e02f2e3e736c086ba17d7f803ce670ea9186be3da26e552d656aa915b5f0aa0fd80e32f318670ee05d0a52a8ddf56bdfdcf1f413b66f4d3173b8f6dfbf8e2434c467f6c340b93e597c1cb2f114e103d7c03973c6d10fb357b5ec91e47f03cb6a794f8b4c3eaa6b2be6ea9a3fd34417373aadddcd9dccdb95fc71a639ea99e0641d5aeb63d59477b8b8629a4012e35a3e167ef445b085403018f7a2c731b88dbb843c3cfca5c367d29dae8346
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a050004140221cce979dddc3f07b69ad9575641e343384e9defefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 23adfc8012add4adaac91852a169e42d92552d70b56ca413ed98dd6e0901b1074381e1a90d59fbb60e2282bd6706494f3a2f200f6d80b209ab83ae45aca3259bb79c34c8652fe2c2a71a4b490a47ffbf3a44a539c5f3e4d622838350f29eced085e43c07a099507a7e9abd1d1496cd249a7a0316462d00235b7ea3b7625b744f
+S = c789f344e0f4e0c291bee6336b3d7d2314b0fa847970df318ea8ebba2de399914ccdd085ca5c48913ebe9851a29e40545db646d958b9370e0c59b249119b67efb26cd864e226b289c62edda506560ae976f764d575515483bd13093b28ee85d4ea62fde932d0a77dbd81c971e7f4386fb79c7f4fde362df166255e05bac5289d8f74562be2daf26513472f472b68828b402c4570a5cb8fb027518a29c3c78a35a9fae810aa6aa2bf0333850d6f71eef951c4c7f315f00be29682121e471cb8fd05b556e995d96e51d4d56f0369abacf234d19e43e737467c14e82e05732d521276b81d8a75eae5a096692ded6f5b56fdd22b719a3541ff98dca661778c25f6188c756543bca8b8ef5a29bd801826fa613b349cc24e69ff4017805e181fcfbd8e947a3d38400fea81a18cb8c151a304e6e39c0e86b57ee0d0b1acd7c052ed94818cad2a6e75de2bc7c46fa9ffd9d37b9ce05ca53cdce91ae58bddafd5fc626ae71073b1efa0015cc9df589ae73cda5563f60774fd559e565250af8b9f2834d2d2
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 94f581408cfaecd499c20c50ce61b30fb294b95bf1a84c79529788e7e97547e18e0a3b298ec13a08a0c1d8901a593b2564a12b3cad5e6961de27427fccc6635cb2e1ef63dedacfa6aaf34a23aeb6d54634942cb0eccca137e28eb42eac60e5e6e8c2c674e60d54b5a1a18790f43f287b0ab4e34117b89d024515087bf20c7487
+S = 2e43df8eca870c60a75965eccf79952b6251f216e8ab745226963ba9200b8ba9a99f9093a5b3df5f64e496b73b8ce077b76f4badae288c3e979796f88049ff2ff7cc0401b0f31c48487d01b4ce4854c4f5afb9cdf7b10ca196b665efefe4be742b2db236a379660170c3f684ab76b69de13a3053c403e8e14394379a0e1a6b6ea6ec501e95c17d6c7c728e08315777d29cbafa972d483d7e7ff5d9b97a8c7606300a03e57b92cf727cbcb6f14ae3c22ff2d417481ffc180a378e4fb1a72efeca8231b5fcba6b1561659d8ad96dde28a2f4360ddfce2c598428012abb2ea530b3dcfebab4e3b550cea5894deff740ace9ef4bfd42337cb2d186d2cd05a27e35d37e04093ffc0751f80ca4ac2c3b197c9cc60756029ee0febdbff2c9cd69cd0423a37fe4560a1f8805ce591455dbe56bef0cf8616901f682bfcc1b58049fc8e3ba40f28611822413b1a04d5ead7bf3cf0ecd94ef6bfd4716f1b1c4d82f70ba8e71de91f84b804512dc037bc17a3de87a74e8c37ee921e2c1a03e7cc9768e3059dc
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 2456ef08c07fc1ec469aa9c73b677af225a9f5f6f8d0e150d1d65e71e6677609bd44f5859de97ad6436ecf75d5ab76a41c9f84f6ed13b311e87ab2b3661cbff3ac7378ca65d5eed14f54fc4c34e3d7681cbae5c1c1fbd3274395e2a21d6881b358ab21ddfe8b4564d215d8553e56c4c68dc1c05f5ad1691a48ef9546f495e4d2
+S = 0631ccf756acdd39dcf45947556f56418b598b25512f9851ecc826e8e15ef8312b12896c5046736df8c36c1e80d43abf9dadfdecdaf48b6a79a09200008695e2c7469c837edce5bcc6c86506908be7942dc6e498f9806a921180cd0b997211afa495d1de016a1b98ba5aad0ef0b0b1f1ac7c8dd5feaa44ae69f8edd6fbe7a4b196ff96077090d2bcc05a675bccec3ab7d3b6b63adbd97626494e57d03ccec82a4ebeb2641b07228de82ce892e24df312f2df624235b00495b444232c205a5001c0db68c06ef7112c8427ae0d563b53b16f9fb1bef64e59cac4694884204f3cf3022ee2471c158e70ffd552ccd582f92eaacbcda5a43d4e4d4b2e72b2193e34b03b9ffbd47da3c0482593440910dfc334d74fc1d0dc11e74210fd31fcdccb7ca2d01931ea6c75faf1f7a32c8115b0661ee1e3457090b97cd35ae36d34b06da17c047e785a5da9d23c048dea4c766849792ae07ec95ffea56686fffd71fba54d44fe8e3d2dbe742a97acdbd7d54fe3a78d08bee547664a0f1dd1544b509b5d12fb
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 29fd9ed0a8ca9609d8e67edcffcbf733f15581633c2449b1a2414115cc04763e3c359fd58471f106b5cf3b3d1bc42e2d2744fc17ad2a264950da8ee53a25d4e3106ddf592409bafaedeaa2ddb57f5d8192d7cd0d9706c4dc4bc91a385a6dfd668bec89e4f25a98ee677fdc4637c62b35195619cd637ecc727d560c9996a39ace
+S = 71265c24f74301a5c2cb797274c15af942ff4b98aad737596c4195fb698a69396cfb5e967359faa0f091931fd0ead53859ae16c1fb18b071b20dc0e8936b58a6dc8eadc773ab583525b1b9c01112c75acec69221d5a214eb2295a26ecd476ec37d8f2ff62f7dbb7452f306d3c4851b67a57fe3e6d7ff98489e47ec0768e3d701f13719f0d8f11281ca4fd6bc1dabed86c9d51fe187ba5a1d3187465e2181e4fc76cbc0ac42f287e9e4013dab1926e19d02bc5d7b84605111f5d2fd63229cc27d8a0e3378646d90a44726aa6f0a528e86a9b9ae709aec1a924400b67da5fc4d2cf307b810e66bca0120b659659882699994764d3eb992ea3521f40e8fde04af2f84e73e33ae5172f969b05e11f55872db50c1d0287bd331850025e3a62c25c26deec2605a4012c0c7ae8454e3c27ba299858930f3b384188c41b5302c83f9032e45bc9995f3ec5b3e5de246eb0bb791afa31523277c26a590fa67bbec78b7934d876f8a8ade9e12190411829625a845f0cfa48bfbcc0af544a8952d52eaedeafd
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 092a5bc0943f3cf6a6295b47ebfa4c872f57f1a10c8a4040c6d246cf73fd6ca45f39fa78ae28d91b43329d65e11fc37090e5360443be1853b77ec0e79e24ffd8fdafa842d3334ff6fb2b50705311140a1e2c8f6fa7aa0d5128ee2f5fe92b3071ac326d06498825f196bc7d4f89f7c7bca1d503c78173a6a3dfca9b1f9c3b88d7
+S = 31e1288d0923e5de3feb553eff8781fcc91fd118f13e2c931e2ec8d3a102344e9f2069bcd3e9b863911013ce2e6e58948123435fdbaefa122e8393cd84abc653559b2958d643ed93431639123aac801ec52578b8e8250d21d32a7edcba7d639f890c3675f664db36fa859ee340d9c90d560b6e1b07a82811a0ac875e0061ac86ac352d33c1760c3ecaa86977efa971f415e3c4d878e5c4d6cedf865b048d78359c1b063713bc20f89a77962998f253920855f80cdfa21f54cbdafac23e259f6de785f8b298aa9e0363a4f098ac1136b036f40c8ccb87de2751ebe4bd4791be851537352b5e813fd1f82d3042853c44fdf645d47dccf149288ebd41b4a583a8887fb01ed1dc7cea237a53649f62a94e3e1724cd409eda8194d39c047b58c43b3210050ebfa39551a4d1128ae519ba23b20456f0d5ed259342f71e1a40d3b84a27afa1d26a1e4d3e365975e9e92c52802dbde13a239748b1644b528cd824c503e6dd4cb1d146cbf1d5a96e20c388bac4bea7b484c337c7b733ab6715bd92dcbc12
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c87593553a6906097c51fe2ef6f4de291844e6c083f4abcf7f2d581fb
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 729c6a3b890e20387db4ebdeaef7e1036a7e59af6da5952ba72ba55a402a874cda4d9311163d17cb595c3e07d0b6364eb13591f6c414ec3e2395cf9b3ef7d54c21a20d34faa69fe9d563b309ab898ecd9b44fee077b0f97182938187784bca94cf059f4e3d3002ba7a321389475933a8af1468138d6303ea4e8c81c6f810b04d
+S = 31a04b5bb1588d4410472beaf2d6ff86d514c30456ef16df2e0b92dd9f26b7782aa0d363d1e3035546d7c91c6cfd05a21190f597103f3900ca12b51922eabbba0f9df47010efcd5394263987c7b79bf8df94ae0318aba4a14caaf791f4a0807bead368a129e201d466e9e70868471e2cad83324e1f70650a2e1d11d9aa539c98e29f1991226357e3585eaac9c856027aa3ac418fa72f00ab71738dd6baa3e8e8af0f30fb58c02f50c50bbd64b6dc1d693fd5d548ce2e0e0dad0ac2936cd3bd1c16ea2ffcd1d2fdc683aa5a0461158aa5e621ceebe36a705d4a2813e5a1b8adeb44718d1af3124849bbb3859db3f8114374c6680cc80222b214ee737744eaf1b7bd400345782fb4df6fdd9e4116714028886e250847e7455ec466465bddd55bc4f67e5ca6048e95653592c9d0bd689dc1ec88aa642f253568d3cc00d3bd719b90e8227c3a1a924f58a8ba5fa68e0b932bf3be5441e601a8466111c8ea6eca21039d8605244aa07952e6918291a2a58ed90f111ea075954cedb1967d4d80bd208f
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 1399504353d5ebc7064355b017edfefe97729cdd100720cb16bce8fd200136ff9668e19c2bac4afd6df392159a500a3cb68ceb19da2648c6cf98402fdcdc78bbdb2fc92f921535cf419d20c678e6bcc72be2c6f5085a700008329e9145ef54e90b766fc531169484aac9678b57b7fde91ffc933742ab80c2ea1368ed0441b3d0
+S = 19e0165b14491e2f84f6eb55f7d0e3bfa5ce45d20067a7809def939408a90b0cb60b3733081960a0917981a89c8907ba50622411958982b37554b40235c28bd478a06d0cfc3aa628c6685fb739a4f72cbd3fa6b6fca3b2e927a7a79fe2d6513ad8e04317ded8873e446eacc8e600380d450cfaddf32523ed7bd339f3f61638bdbbf80ea2cbaffc51b2e14aef079a491eaf55c7da79189327070e0c66daa906646095b2c0062850d9269a456bb13e632e5954208fa9d9a576bf14c958741f7e30372709c20a209d0fdfb0e18608a65f049565b25a77afb4a3d79a49e9fced249f6045d95c83f0ea4b8595288eb022620a1a6e6768239fc95867c575338514bb8d16f4595b6463a0bc576f1edb72c2cc4344b1000f43447207f2ca9049c86c6ec92f1f74b6811b65534808ef659af5e3f283a39b9921ab906a51a9043bc34dd023c54f2a682f0867bf543ac02b55a13920f8c5295b0aae650af71083f7562c84bad2bb0685b0d6101978ab5d789b88c3785d82a01f154795084b6e363235b10fec
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = c783252ef5e96363cb48e544342f0b82a98334cfa425d5a158cfc8339f3fe6cd3498d746220529c77c9fa0d14f91cd82d579e214eb12c5a6c511633fe14c471039216bf9bd164e4f00bd46dd32db18284ec8c6f89419a8133a7dbe4c5fe545bc40e88850ae65f984c06a806dc55413fd7c3887838882a6711edc81620152085b
+S = 516e3483482b42a740c475678c4954ddeddca4f5d3cbb9474aa7fe7ade371f4ec09d497ad8f4bcc33f60dfefdbe3bb66268f5bf25eff3a6f4d58b2295c82dd977933e237fbb140f9c095bb31b091e0d8ce862a588a827a3ed7a0a6b407c534c37fe6e89b047042de8119db826edb202cbbd6188820371d7aaea860f08e23cf927fafcea8f398c3e189cdacbe458f3804131b6cb8f32bdea4c8e88dbab79b5493928a794aa125a102c2af675e8a1654489651214793bd7b8e86bb237f5fd19ba5c902986687e18390604a5fbe531cef3d1cda48c7dfefe053bb3142ba153256b1aacabee463dc63e7d74179e83101aed8e9c140f51ea45c94c9114f22d9ba63aef338b87c975f3453fccb06ded002477a073f40a4e3a42df7bb588a5aa830fbefa8c7f2bf363bfe43e236d25f8c0d0adab69e3b3b1ccc756a5e8edf180cc5ef3d18eaea6ae4d09e407a1783ee6a4a5505a90df31d310dd150e6aedb20bb97b2551e6e96223aac0b3484a6179498d1b4c2412090ad5a4d3dbc0fec1d11d8d0a813
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041caca1cfaac92548bc1743c2fbf38354db0247dc19de0004601b8c68cbefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 5c0231e10a12e268e08dbd3b86845a1907e6bf853552e12e482a68afc7e9b378acb61c0cc3397d6e53adf3d50036e1a7f07538a52d5af6634a3aedfc4a22c603bd6a45bd2c8dcf8db73829affda082293c19b4ffb9e5c7a76349b6bcb3e676f7d647355a0eb7e0ae5655e730456a448834f9bafaa3985ae0d97f4c58cbdfcc3a
+S = 1d7b0e1ea89523699cb8ca51a9086043c1d3c4e2d0d0dc5e1a6f3688d318f7db0d2a5272f71915ee2439db175714b2c38e8c0b27264c8ee01bd1b292b66197e023f6b49dea082b469cd30289aa5b2079e6342789b1cbace05ce265e5fb1716947989e5ccbdf4779a37bd4b748ffc91c2944259ae2de9582334b6df1c839160e4e704cc8a771d371507a68c61f3a06c46a41e3aef02162e9f20c85ef51b3f15562d2b9a512ef0e81ad60f9934be2a2cf7e5f54813244d360148334c40fc8a2e65335bacac5b9a607d70d4296f56803de8c0840653ae2837a7e826dd4569896555395bc0d4262d9fc025f400859421bfa8cd5841a3375e22efc9c1538e78795e28b6eea359da14ca3c44ee30d16e7359b7d83d47b6744099c345ec60bf2fde687d0f81db3718d3a79e4ae86a0c3bb47ef0618342f103d6e6f7ba89d4a4a520b1a61b2d8d3c5f178a46166631b58921b7e0aeed15c175e85f76575b746359ea831f87c261695896125032d7ad4ad26014abfd7742d5396dc1516f46dd273cee88bc
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 70125f4abfb1179f8c2b4f4cc30386a6fbce13786050b848f0e27adbeb16b0fb849e5b77dd6ab56c32110dc35572d1fb5a9bed2893ea533cbf71db867e9f4e78081dbdad1ff7182b42fcfce52467cb845cbf02665efbc7e7aaeac2e043d22e6e635830f56d9f676423b4c4ba192a9cc96901fb39a9cd3cd11a13d6f222f77964
+S = a06c4d12aba140f9db9ae4dad7a507c241cfc073fe16cccb8e99c0793a0a605097a0538bb4849089473050ae1873fd369c2295dc98b5561f975a66d32caa6ebbf887428b163a9a0515a0f614f636e8e8a87993c11fb334195de25c3cc9103a9e01f5bf2b6b6bba1786b0ef02e17c9256aa8fc714fe5bd7c905e240c2dd120662ff4ed31c229df92e0c819ca384735235e5f817c9a844b733c4c125498ad5493d1651ef8833886d98b409b41709fd0d0c20b0c91c666cdd4443dc0aec4e3d9a844d28b40b36be972a99ceebe68b955fa699229bb393bb65f32f139cbc42b20be0481aca045f965ed2caca3d4f7802bac775fd0032967570d826361620b32a2f230600aabddaf976b1998c9a5ec545fec80522f16876c4fc77e0867867bfab4b167fbee839b83b7f5d647a902e3118a167b0a7c7fbbc31f23c8b9606429c66c46a3cd7498e14a94fb315360a1668025ee35bb49fa614250fefd9236b8d3be9bdb271f865b460910149449e7d22df7dee27db29aa123bc31915cded3def0249d2a3
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 29d9cfca7319f6e6ae00ba6de43e9f20e140ec7b45f76095d7dc21491c31f5932989b43cb58afeba72f229529ed87d7fd435a49729a25cac74636fb0eda5e5ddfa047854455048051291d0ced04819e7edf82d7defe5cf9dc11c69544ab346154452015a4cf33e8e35e5972ba217da20d4937175c0492131650ef87c5ce48001
+S = ac2b892951ec306c6fc6c0550d633819a2d4f073001665cbaa7eceb96972e7b0358fd49f1fddfefbe16cfdb78fa15e4174b5d3e398268da9eb23e6b7cd8bcb679079106f583390462850e44b23aaf0a59dc9780d0f3b15bb93368da8fdefb979b2220241af3e60e5c1e2bcf23e2e8657438cabc2ba22e4081889d94f2abcafca0dee1e81ef1c29d3164d86fb50d28ebcf89e362f9eda07cd85206b9351c6092d37f0cbd1765aa81c4e0e18bb01d204a3073e1b60fe67c6233862f1739f223cf79160154c138f01d4428e76980e0dd9c21e1a701d05a6e67acf7f257275b383e506bcdcd54a80fafe266e87eb36b3c076589d1696916ccc88e4af50d8f3766e6dde0e530cf747d814a591e5da6bc977eb25b43df723e28e3ff226253d07043abf1b8f5a013b2651de9dfa34b7ffd94baf8fb1459b9fe305bd58064138a0ede6af36298f3444086f1a7d0c723ecfcd6404fd267bb20ad48f6655a9a0886868a83a214957b40af02064692661c1b191aa828339495b3de0c789856f80e5b2d569fd
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d06096086480165030402010500042038dfa46ebe6244537c96b22aaa7542f8cf5a10069d87d81b37f93a2ff7323cb2
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = adb245d4c5c72ee661b657c6efc444f8b1bce6b8c0e1bf905028472935a48d62a742219f42b6326350b5f4224b6544509e128fbeac22f026134b9805320373a8e938098a9f42a2dd8a16ad672abc628f1703a7b8fd7330cde583eb1db60c9b6afbfec23ce652c57b953f4b3d95b1e6dda5f7f54dbcbbc9ad4d38061cc9a74cce
+S = 7f25b51b4d94f2220ff257205e640272376993e698cce9fc5a9b429ecf8a3d6d4150341df129b74030afd5d092858153cdd01a38a586c05871632525ad7b9d433dd9f8b1436d3d62efe46501665e075e918c39f775ad6e1e3e4883a529024193891d9463b0d1424a42890d5c05058d8925fb4c446510f12afd6457b50cb611eb0ca641b8f2f2c0afa4f03e98d154447497a4640405676e003f8a2cae21458d56c59785e34f54000b6105e85e25e4c380db43c71b990d3653ac344e2bc72bff987d6c5249205f2770998725e88125309a7c49dc28f9e6fc8a1340f9dab47fc6507d3d99fa876c330ee8183827db1cfa6c05179bd49d5e4bd6b467d559731417c9b19d0d265bd7cce858178e15cda9eda4b1ace1f6a492251c4e591945d2749d7ce65e8c03d57277e6bcb0f097c13504f006405e879616d95b5b75005118830beaab13538943044da67867877da87f29183fc05ca754df6c5bff810b6e5dc64b9e50ad29da9fc74a2fd20ccac5a300928ced1c3eb719e44e3b21071746fc559b1f
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = bbaa076712216e08ed954528d8309ee685afcd901d6865c4d48b63d5c0a8a870eb71ad80a7c2724e21deb7ed39fc6fd5910272cee49072109a4030a8992cef1d5db129544b7382b142a1fa7f747b66927411212a8f4dff1b6033822b9f6851bc3af1e5aba73e8677786776a630b56c645564436ec6a7f42e4fedc2277b63b494
+S = 477b191f2d027ad6621e38d56aad700749444fd895238f9dae3633176505d798d670ab5e85df8fc42906949ba36090a14577e9b179e6704be20f1d3ec2ff00b9f038a71956ee353f358f608d1728164fdd3b90213152049f2b3588237a8c1530f5333f0b89f07443fadaf09e80122ecf2af6c2dbadd5e189f35f9c2cd680118a2793190d0d63f83e13edbabfbd01031b6875d9c7fcd38bff3587021ef04f1ea0777ac67e76aa1b0773109b869075ae2c4c1f0121782ad767a7d0e78f3170c3e3243309ad36378a698f39fc6591463dbe9c84292bc4a44b4874320f9c5cc3cdca879f2a015362dcacc5c74cccc2bfe05f0773f3a836e1ec511c72d9fc7317deb4b2af5976bdfd1fabbe15b3f99b498647d92f818f658f8398c031cf2f364ffc106e75ece8f1cb87af2592fc4661f80c45e76fec99545c54dda470a019ba9a26068f05517defdba0d423029580ffce95b3ae1e5c8a882806f40ffc3b78640d6b311c2de8b0d51bf82a1ccf304975bc413d5f7e2222d91e5d650ba601594283aa49
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 7e5a48ece8abf0637665d2cc4df0476da66a82006aefc2100018cca662c1992577104c739db3675984683d2d43c3abaea52c032fc42749f8dad8a2e953c6096027df445d66bc16e41527b7a338da81d5308aec664724bc588a577965d75220e636cf18f36c5067cccea8267754be32abee8e25ed1b7085f9b79d3b6314ef467e
+S = 8b08c4fadf5a33065be2fe7b2487190aaa863d150c819bedd2de321ec34b9f397e5ceba241c998d1138080867a2931660f6d720099698a473b10fab8c6c1ac99bba21ec964db0e9de0424d12565bf20978a6041b8c72019f910c286781c7979a98047abe06850d282644f6b7f375c6bd6af8509727b0d64d851902baade451f6af0c21967e4d545a535ada7f59f23d90992ab1268dab4797907527b9929cef18ea468e4803ddd69f44627577e9cec0ed8219a659db94d46f560cc1c32fc36537f9fbd568e26d22d070c82805cd17cdf80ef8ff1129f5254984ea7e13f3b1d40f7d9c304f49b504b634807f77dfe73cab854d3b98878dac4d33d13289d1fbe9e1b2f3c75f6ef5e4deb2bbd8e56ee6353f2a5d9c28d4640b01777b3bf743e4acd53e2e413dee01bba20d1811c62c3ffb27fa6a6a522dca12cba25c0b5c2f02d3f6b4593789741aa8d2e111b81e34fbed7ea544405dc0edf263283fd28249665001488c67f9ca067569f82c52587ec438b54516d1d84acff50719049e64edd562ad
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420c46cd19378dbc903c60d48ba8ef26b1ff32f64f6612a2fc01dd770c878eceb8befefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 2bc088c8b2a4af1e90a9023b3216fdbf89aab7710e8b0bd6037ff503fb5e3eaf9cc85c8ca41394d82a87612e27ce19a334a6ce0e95d972a7776f3fd47622563f6212a72c43ba100a9a23c947ea57ff697719bf5b4ed3160485d0771ec4ab5c460508304f97816ddc69e4022e859bf73adb6b53ff40623e16b60a638beee398eb
+S = c42b0d458924349b4510e4805a6f199b29defe24c7220c54d1ddc44117bc05c5b25858939708333c8fcae96efc75e1df6c6b429b2f0e3f9ac21a59e15c1a976fa91294c11e255139725d5b9ceffce0bffc93166057d191be06435d68a64e0d790731f00fdd868dd2881546f467b52d3fd240cea6b6e3883db18facbb67ff858918de576f275d6a0fef13fa135665928a043390607b964a8d395117f886c661d9a9f8d3a2d863292bb2d82c987487180dc2fe859fc20fc5ba849399fbc2a5bbc414fb244003b1887d945580d2bae524d24de03fc14e5595e7471f14cb212cff64d561de03d5a85304a51883a10c259ab729e750f8a424f769eb8ce2f12c2ce2b3835b0ac9b219a22b5725149d65681c525eaa55ddea7f674ebc833f74464302597cf603d95fba141b8ddbaf3a540df6ef9bda7146f4d104a9287a4a55bcc5f7cb4dafde9c437d2172cebab2278ce97441cd1e091e3d18429fae503e1cc23319ca6abcdef6f8562a11fe7fa1b283f4c81a3025668bfe995dac330bd0a3ac869985
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d06096086480165030402020500043034a99a927444c010c6a1e59848fda5efa3d6f47f1dc62aa4a8c085308632d72f89e37e9f74f5947755a2dec1ddcdcdf2efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 52e616af9542cd632f93bc2f3d510bef3dd341572014ffdaa0b6eecbd447f6c302c4b142b45b1f990e759b075ef40d22f5b96278366a3977ec72df8ae1497e85acf59143cad19b8df08d193ea076b5a5fbf7bc2bd660d2360fe7e54d21ed5f7cf782a0fafe2aab097ee11f1e2a5e6a42f69539b8287f32e0b21de65bbfbb0170
+S = cb647fd846c24b61bf5bd7893de079147a8fb4d447bdf26aa871d7ef83de578a383d932b152bc28ba4baa5ccb15e499e338b2a5e3606533c62915a26ebd8351212c226265bf097af9e30f113566921dda511c72fe0fb114eba47bfcdd052032abed1f69e144ee7c347f62f730b96aa42b75e23773d2a65f0d5f63e01c395ffe6c9a87c2364c05983e4c676af4b57a2190a2bb7f5f1b96574663a13540f51da353be8876879a1ac90b10a5acd42a69b6ab45ca194fed641acdb89fcc2d93325028f01a3149795a2d95887e29e161902da1708410d37cab1987d4f3265b9ade7c1bff7b385ec9ea1221fe00a285a77b5ad37f1e8519326d7baab48fcd70aa52dc2e6f8e7270e2c9c99f21b30d217a62969bfb584ddcac60959f71d0ae16cce6a41126c9c597970a79da11e7302ec710df8890afd0b133306b8f8a2e1c67a6f0103cef6b13fe4c1b19415759291267b3fb0dfd552d83ac856f85859589c69d911c9e498160906833664437456739116626d03f6f2028d869218b418b6b9360d536e
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 11a710487cbb1b9392d6f6c305b105f68df8d5d6384e0cc10292a028a5604835b2db30b1e1aaf124a541c03e0462e575a6e370f02cb127a4c315c2bdf8365b3fcee020ed0d834b6ade7f549e959e645bcee20e40bb823adebc2f611a309b00d28c3c46c4aa4e10ab631718aa5f6e69ee2c7e17908ec82cb81667e508f6981f38
+S = 378ea4183be0744a9b81e57577e197b4b20f3e9cb7fc455def83eecac3f470e758557b741796439947eb6b97b46b3e67c12f30452c04ccc3801496db5e3df3b5f6442b7086eaaf36ee1a43746926e78cb43317259970b71dcc9127fb41668845f0bc7a938addcbefc7ff19025f4c35da5efdb74884a98872119983bd0c1db06489b7530caefcc81822e74fa635ed4aa441a48b8b7d6d64f1a489d50fea892b2296c6b1c24829e7f7a23c186dee29d88bed157386e4090caee36fe5984aa09cc222db2f5985dff56fa97da47202fe49efac993ecedba74132e144e3ca1a5702127dda6ad91e133aa6e53d3d5cb8c81b1397b8c8ea2b55714f6559f198d8ffa7aecbb12b2d4bd99eb697a3d26ca55694f2f1e99e543d6be90e4a21214ce3082d0848f3c141c98becd7f986d5684e67a8cc5b783d90aaa7e0e2f30616f59f38ee150ca41101c4f20ade865add34fed3727b745db406e91dbdeffc40875dfdf2ff0dc62a8d392b4272630d3b17ccdfe39313e7f8f265b2770942f500396d2e2d97f9
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430eb5d1d6ac4370fbf37da65a4a43e31015aaba587ed2b1720edc90282ab022f9581f3fd35e174a5be58edd5f9a9aaddf3
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 979982a68d0d60a1200990ebf8a49a7b7db3d1e83f9ad9d9946267bc830c48bbe025a5ebb99b85c7f1cf93de2beb22c8e9766e5ef526242b01f5251d8a768780026add2d2d8fb9ffccb86f8779221b01d206e586d96b83839b3e006910a4bca6438fb5d5b2900431f8ecab50a9f18d0e7e8abec7b212fdc9ab667f08dd3eef14
+S = ac48451dfee18a468ebfebb7300d03efd9231ee21d9a3e3bdb5db9f5ce8d3e1ccb9af7284d5a98a00c39cf62d9c4a46c0374808b0dc01bc57ac8a61682a7784279d090d5d57c5b4f36cb468fc9200e3c28818f5e8cb14bbec20dc460f2721cddb09233f64b0fcf7fa00c165395a681ebe52fc8673d7b18003c4387ca6c9487f02912cc15e525531e1d40aa79881e2c6b2038c5938476d4649f20957cb0405c6f1dfb14c1986235b7f8f18ebe3c47600ab80f841c100ebba3e042d865d0fb8de4708da33493fadc509683bfdd16c00c5cec1fdd7d3017f4a0718a615dc7122202a54ea7429966e6f818a4096db8f0ef3e530780f09eab5d96bff59869fb8c85ed059a3ad8dc3d5613f3300a8ed17754228ab4e38dc24dd8127ac8d4cb7a68af8aefc87e94344c46868c1562942e188c9618be86bfa09d12a16aa0b52a7ab493fec12eb8f4898bd000ace4c2520d6713772b524dfaa86655fc5dd140d1d7ed49db225c93845b41ecd10b8dfea26adf2761733cf0d330feb9cd024bc4b906fa14ff
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 7fa4945a374691fad437ab261e2c9068c7221fb14ea96f4a2483130d0e6d9cd5ca3d6033f52d7a632c77127e7222dff0d11be92d448794a0d558dae4031ed83766208c2c96acdda048abdbeeba78496752f359fc82d1b63eee36c789d185337b9c77a0abe16ac19870fc8fe0c0d9d6b390d1f486cd2edd0cb74463624049b58a
+S = 9e8ed5b7a3863ca22b2c2fdcd28ad09e69346c8d14262c7800e85ddf71b845bf31d2101fcb91fbce1f227ee1c72210f29d995404ea2e4b31b41a71173884570c2fa0753facadaae01038e6b897940e386b601e972d84095cd7e51345348d45a653c1ce707210b017c1b32ff4904eadcd34097af48a430a0147499a9d9ee8a765258b94fa56b0185bb0789cd222941eeaa8356964d2b1b12c81c0ad0440725ee6360c9e2f2885047c5b6f2069590c0f85352f5936e183d78e5a152f6337e1643bb37de221291191fa4226973f9fde3c688fd214c49ba3ca6df5a09bbf4523ead8682835944b1f7175ae038f84955dab509e0d68b5d9da75eba60e11e4e9ebb4d0f2dee448694f952eb3ad39e740516f129d12874e29ceb895dc87dfbb2ce4f208d1e646c347f9682dce4b71ac53ebca2a499ce64112279ac439f5942c8d04f2bf5e699000efde4909e6b6b62cfb52ee384e31beb22b1799731c543c4a95303f8fd32a14d7c0fcc4b449c9782af392800d2f7bc37369293f49c1cb94b2921dd407
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 831c38ca5421eab1edb3600fce5acce059ff4c5b38b56d69fcdaee5c045fc6dea164672777084574277f92b42b654c8401517a5d8baeb30cb6c6df635a20422f610cb66a2c7c37b13215a5f8ea86c67cec198bf95387941d6511f53d76cc3b48093daaf93925c950579e2142d56741b0627d059657eb188552e2b853200cb911
+S = 5c95df8ef637f77033e66934588956aabf334f0f5ca5efa1bb0e5b1c58fd313cdacb4d9f3163305e048d2f33a9d101fd6c0670f96d67b466d11f03d3aba60bdc04869e3a17aae7c80080e146c114413bb6f6016653baf26d3516fc05fef13149dd552bf5149cddaa46b783e625d5a3a0b859563e9f467d9a2723e5efd041a92a9837d4b652219d4a9799b35cb3df6c80b8467338b0e7c325e0dc1ee22387af8877e66c6f6a9b0d12a83db08dd4a843dc0e7d0aef5f0ca9cff1db415f2dfdeeb3a0525b2cd32c07dbf39eb9a3a132b9f764b66ec0ac6cbe0e770e1afb063cd1cbcfd8e8b39e10c290ab4a8500b0729a1240c772ef5adb065965ba3a4536e2ee0058cb11ea58834a5ff267fb11e90160c7a433bc1af9a044e208265e4c62b5940fde0e168a8863bb398305acc367cdb1c3b70f39ef051ce9614a125c3241bdaf42d8416d4efbc003f698878829dc2cdb1dc1f7c0ffb1af30b8d807b459403336a2eae1a6a497e95a0667a2f547b5d40bd97f9d76259c3ce91f1209a00e8da48fec
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 939cc087cba5d8eae6cd3884251f4d60808bdc82f2e6f013183217befa20cd5929d339c80ae7171e71b2f60671c9a36273c6e53186496ab6f63d02d7205d0bc384f62cd71cee47c3ed05a8e8db5b8305c1339d13c1f6496dd97b9634b785c7f2cf8d037daac24e1f814fb8f30adcd49292576cef4cf47380e9723b9f68a1e92f
+S = c80363c21f7f20d91361e148b0a76c33ab2109b8c8e34609f567b49ec9675f1c04452715371913685f9a2f88effc90f3ac16665a2dbc81ccbdb4cdf677b66752fe07577c9a2986e48bc03e12126bb5212d7e821adb66c4eb96c267eb898db16f0fdc52f8f98797281d8411aaa4949d41815133a79a7f6f8cb3893fa1e28a37ee6c550e17772d5be34cf4b2cb16f119fbf9d5f41c411e1d2561d33aecfd9fcc425e287a650b127d11ddb2fe49a82ad3e7cfa84a4da75615ae23d0cbc45d58b7cd4123105ce3444a52412bbf09c08036f10d03d79ee735741858017181262fb5e2f817e0c53d3def1fe84c53807933bfdbb2ac2eec4fd96d638255364033e38ae5f9cdab1241938c1f6dcb14067bd236cb69809d95349d9c1723b39b71192cfe0c8a204c142a2a72d67f124ad6b8804d3b5ea149c7a1e884025fe56bc7ebf925d34ca62c285d3b290eb38fb24e59ad7c47914b98d55cf8d1685f1d08d1e919f314994a348499a68d3c669872a113bc119fdede411f4318dfffc8082e442784b68b
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 118a21ca36aa54b42804f7fb07874ba74e14bf3906dfc4343a19dddcaaccf53ec306f670cf39971a6ae2763535696613ce480aa0ff70a3e735e826d834b892480a058039417dfb5c59f693d47651ad3d55a51ded849af779d312a17b060f2d93ccd1e6acf53e2981df87775f3109c72ccc7121a8ff2468f3fade785086987128
+S = 5d1fbfceec266986ee94603ef2f57ff87959bcb7f1677fc871f97b5e73bbafb6885957eb04616a3a9bd010fa46c8a5c40831944a7f506d165ef3cfa4d3a7bf0768360e8dc0444c2b7a2e05106cdbd6e3ab029c11ebd701fcee53bc46acd269582ecd7635178b850ebf2522d16bb4e6671ee7dd1d417cf0d23baa26237e03fc0650462c1d113dd450e4465ff18d3a9871fe5fbcaf554d14c0bad78752b4c048356ffed2f80ec319ba816c60d06e270c656c8687be145df46baafb686a9b74df7347c8712dfe671b33aad8b3b7eeaf6322a8e770891c8e03526e1c6ea4fb9dd03413d646b3ac78a3f6b28ff87612616dcf87efbe12ebcb6933bfeb714961e8e153f96ffdbf7777f6109be52a936a13986e4e8229535f51a679f7d7aad4acf1824bf0616517785b864f5f19d275406ec53089a04a4f1b820d167b5ad3ba36910a9730722dfc58fad54f1e0d7f761f5d4ed3bff3037f79361fcefe723647c65811f4ac66dd6dc4e3f5b4bb1cd0f3d2aaf000251b69b9464a35bb7f7540b1249dd39d
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d06096086480165030402030500044022b0603ccde4538899af30bbe52e2e4d6e62ca5f5e69a0e7cfe914a193af2e5788f6bf85199a7098078438b5d2a3b694b926526033922915953e113bc4b56d3eefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = 465c2bbd78a5f3bcb387d0db7910e9b2d0b827948d949a67d2cc19b2d64f29f8e4c52145a7c68b06a449cc1d085f0835a421405336e6bdaeeabab2c1200c1d9e70a7ee85ebe46bb5a41dd382706441a8e975d4dfb9ea0db015ae788687b48f08f1e9dba6cf675c72bceb2b3238895eb3a89e2c609e0752125b90b42a92af48de
+S = 902cd4cb495e446e0b4d4cc1944fd9cddb126dcb60543dc32c4ed0eb4e72182b1a13459746e4ae37805e23808cec5974083911f1c3f155e09a3223b03aa145128c9a2ead1c7010dbf43231b6ba5fce2ca77734e543139118475f5f3eb9db6c0dd00b01b7a48a1b4c65cabf9260d22776bd4168a7f7b8b81099ffb60d6ee00356cc16cfee9026fd318ef4f0e71288daf10e06b6789fe0c590ccb7c448b7426dca0329453633d98fd3917562a2df5c2a1ffb07f82354b8e3b1a508908314245767542b856938e019ff4ee00c46ced5b8b836b57b9d0999742b2e23dcb15e66c49401495dfa7267360eb0493722abe6c89cb92d47aeac5218a4a949b4d7c4ea23c7448995294424995ef6b873959fa8f670e764a59cae39e998459f9eb03f3f640a6c4a6c39a9532c48db61b5d6031e7098bbd836f5ef887c20f00e6f8d3e82a7cf3f3fd027cc315b85e93205b78e29b9307d25f6c38498bbfeb08a0aca6975f241df0bb9e27e99dca0b555ed294a23071664a7fc9039838a892bd4cf9696763637
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = cc848fc93ced6a3252fe844053b56f8b8df90ac8ebdbb035c81baf3801eefc424efe25fad2b38698f0b1c08e61a2676e8335fb08f4661ad26001f38e9761fe26e37eebdb9827d89eec8bc6be09fe4ec461fa909c42646df5aa11f6e95c8923e1330bc9b3b7d1c60eee947e1875538c55ce51b1cbfc5d10644d559e9378edd43a
+S = a2771501c8d96b8f29f456930f1551f648abc58e214854d44c1bc32de90c2a8d269ebb1c30456e710fe411483b4c931d40a7c300e731ab0897f976e5c5aced427bb462acb998ddc23031c84efe0d187930254e0e0e1f20c9155ba23f7d2a02f1b390db18c71d37f175d13f44e421279ed5d803ef7946ceb364dfb42114b2943b446ae2eab8932f19a87eb449adcae98223f333a47eb028dcdbb9a8fea2018b3e9bae3420d99d288daf1c13f9eb9932814d530d1f8cd0f496ab21aa984f5f2df5fc5f56a6e7431542864f2ee78108eb4ffdf98d50b8bbfff626da4f166881d8126442331ab8d4d30492473a6af9c1fbb08fbbfb6bdc828d2c2419a302800d21e91aaeb39a453858f6f2a3675afe000de678e5095b9b885d1b02c153dfc48b33470fe8521afa1d36a18e2ebb81d58e1cfed3c0125bc8c5635cb88ac78e03aa6d661dfac9bd2844aaf98b6ac7c753543865c70a34c9f49b33fa63bc7b4f0b4a38279fc413482f2757b287c31f83c786d5a55438c00d1f3bff8479ed3992cce425a0
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d0609608648016503040203050004403c1940aad46377052b5ca5f32e427fc60524134f6b125784071ecd029233a6b878b85b7f3c9a7ccd4838fb9352a468d02f64a6e19ffcf2e2158aef7f09033d5d
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = b493cdbc8bf23247fcb00bc4ad61ee808ccdcfaecde823ff2f04467382451a6e6655f20e555aaebce425270145accd9b11bb8ed144e6fa038ac2a585b955cdae9eca3d2bfc697199d2c7fb54dd3a26895e90d8931d01bd84ae61a101f39b1e54e25a78bc8809c5074efe51637cf24072fbb5759c5f1fb3a9254a028f38fe5588
+S = 301c7cfbd1d8fe0d725cc8854a9ba1c7b16a3e4c0e357373a57cf22386bc562615cea5e5359d90eac51e558a15580622585f4144905b4dcdecca2e42f68010aaf8be6a17cf2fd4a5ec77871c2229912dd6318f365214939e785d2e9d23c75eaf8cb3c9ec8a21d15cf7186aa3e92e1c1209f054c335fbd61ac9c48244ecb4d607e3bed905a930f9605855e9b220129ecff5239eab8260fe7cca7d07af495a134dcd63dbd71c72205d11613ba89925f7bbe36c2909e9dfd40596f2b6956e749c3710587d4f1c304acbadf83c29caacd3a1b3f0dd332560fb8802be3af45e6e09aaae57d8b8c75441f310ddd927a3279243817943719451b94cd6d3cd62c8e1c15070c2fda9baa2534018279d36ccc15fac086cae7d430c44276517d1e32082a6de8d0cd7d88900f9cf4a5e7012074834b9783734dd1524e191a63e0c6eeaa5632f6ff2c92f3d05589791d8e717f4833cb5640d2444074e881419cd521fb7f5f847fc1852c8e17ee7c7eb3d808c9870b1f81ea69a54b361b65c535e0dff70278c61
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 22987d4c34ec4b902622a8a6aff3dbbdca802c7c05de4b35d2402027226d4d5dde12cffb23315451fad250d344806558b7852140a554f05415f570af785a6db622f1dd0c11a3e64bfae2bd0f59fab4f2bbf50e26c14f1c58a578d85d1685e896d9ab6acb9242278394dd91c275d8c9efd8ff0c4ad54ace97ed8a75cf7de374d4f25ca008551f66f62a6f62f564f7cc4af8800cf6c6f65b08ceda624a3a98b8f98c0374e7fd2966ea7fa44c347e1c484c5d1805d81980db5d1eb193f48c111c02b8a4e987a505ea5bfa50956717f77a3b89e47fd8251eaf35b3863c3e32a01b6271d8f793074aea4d0ba7eec8d1cd23aa967c7bde7c2ef919a1a9744902fac439ac3ada0f604e2c1edbfc4349bdc50060f0a0b2e46ec8ad9385d63342c1cf5eaca1c68ade01acd711b96f3e165458d53ba6108bc784dcf36926a5f2e2217fd8afb78f46a7935cb27707a192ee7379c72b74342fd48d7e43b1a446a01264eb2bda68954b310faaf5dc57b524a4942b35f17eb7b69ca39e609e398e9cbb6d7bc61b
+Msg = a97ba5b9773d187153d602d121ec843f36ccc618105046af44067093b78e6e11114441fa6f2011a759dac139f351c725772d3bf1e2c32d38ee3a3cf441ec64fde40f18ccf6959185a25065354e5a5b5715b47e9e782d70ee508601ab07d30037082452b6746540151783154a9ad1e9ddfaa9b8a73956b7da5331e741730beac9
+S = 2f2c9aea6942c5a24b4e5e04875eb5c6f44e83d89ccf1f13455890e2d61f2b7ab464355c5cd0e7e9aecf004a0b85d0cee852a9681f4792899731f984e2c06e47b8dfc4424e4cef5b9f15def45d528a3a275fb4fe7a194ee7b10a6f9694e8e1659d95a6f915fd79e3406e05136b244213ccf67c5e2055adbffa85896591d7abff96f6e68494dcfc48440bf66cae21d1752544933bd22154756ad15a3c664188cca88b5f23a6acdc151e62f7d0bfa9cd60429031736d7df76bf2c12f37c338a1174eb42cb740c5d38c1cf1b682aab8d49443016cbe397cc0c44374f29502d997bde22a45efd0e7c801ffdcf1b3e42e93b955ecc0eac9f5b71c349504e8b2973d894f0d33edfcd07f9fb6b3cbee593448bef9590391d13b661e2dd18f70b43b59f2e79d65905f9ffd8ce0117e06e610f34fcc8dfc72d6f0440e2e6f882747c5416bb8c3ef6ec702164b51309d3df33a3846237a2f0ea8dd39ffbe0a8d549cdddd063d7d5a65fa27acb62f46ea9f467dc0defd426cecda8afcccadd1fa3e483d5fd2
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+[mod = 4096]
+
+n = b10935650754c1a27e54f9ee525c77045d1a056baedc8c1ba05a3d66322c8e2e41689ca02b8e6ec55d3331cd714e161b35c774311540c6410cc3b130e65cec325377ccf18a5d77054afaa737e65b68662327627f5d1092df98c08b60a3ba67599b1406986f441528d2f1f5d6fe5ec6b8aa797dbdb3162876b08298237af81c7004863576af572ddd66c487cf32a82d0f9fe260f8f2681613208aec55723622f50d3cb3bd33b1226d5b5b9ea2c97a2c59054e31536849ec2f0f2597c077e621ddea0a22ddfb1df925c9f1941cd431afce0398d28e736cfeab3dd7f062a65a2a4c1ddca1f32afa03b4ddfd8b7ca40cc0ce2ed42229d753f03cc6d8bcdca76ab7c2703c5ddad08aa9bf9a27740a8b23168c6b55917bd3d5c1c057c34d1efb1411da51ab745519bd92b9432fea8fadcb9a70e5dc3adcd3081d3333507b7b998886e988296628dd7265e64eab557712556cc492377f15a078dcb620a6e7f051a1fb8754efdca3de253dd0aad4205b032659e4a4fb307f074fbde340702b5911acb34737d7834600cf2ac77f62f83ccc9ba78ff911021b9f8ad1bf421430ae0d64916944b504542c0f6263c48e5e233ef1869df1efc2ccf6f4a95e4db2de7b4cb1a992bef6573511bab4bf2cd58e72a0c235f56dfc182df4dfffb69433a5677415f35d84f5125f5200eb57868cce6b74c5833417990e318372c9239a36dca1a0b28809
+
+p = bd4e8bb7fd7ef1e39d71de06b0001bdadcc81b0edf2226e0d056b7eea70b2249000279cc1c04b1ac2919014fc3fb8b62baca3e261601fb0a58a9f67f03cd60085b2d43906d36ad014f321012a9bde9617478a0c10201afd53f2207de3648afd1d737afadf7fd2c0b9824d4f66b2c7dfe93390888ac088c680c27b1b2486659ccfa8986c8c23f78f18b5815a410328e629e7440221bffd8ec4722bba3420da5234f898f8cd7e6d7dcb1349bc4a0b665b41d930e3957cfdc88797aee5b2b27dafb5ba0949e3dd892f490212dfd249f4b1d99fd3b72695ee0652997127f0b9b417fa8365ba9fd103b978309d9baa9d401902cc107cb8d2af7ce04660900e3707ab3
+q = ef67f69838735c055145d21fccb42298642177fe3fadc39070a95e4fc04ff058aeaf9070b4eb2de1cca72d8533bc55206d2ce9f2895b148da67c89e5b6496ba682f76bcaef69306a7fa4fbd41a838bdf0fab3e7b56c27a8c18dc4bf970364dff7427cdcc6f532b49712282370a718b7d5287bfc02c4abc35ccb2eab3777f5e0d8a27ff9ebe13e725aa0a0cd48aee1fa33ea6b4ea965ba42fcce7af3c528a6675cedf4969640f2ca73345dfd322620df9dcf16520195df8232061e2bc89c12de24838f255e7b1c17713ba435d5a351e263350198b3fb881b8ce0acb5aa58b7afaff184489d167c9af21e40e2ba9fa69b44a3854329385c97df0de24dc283a4053
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 200ee1828829d9fd27576e253ea700245c38c5ae78fc76e33dbc4877a55d1e10c961fdeff8b1c0d306990d1ae614872a7b4a450fac578465b74e9879c77d29abc8f39b177a40ce74c47c083b4c8b2f0c449e3c4f87fdec17e405b84bb96c0807c4cda44037606ba70a0847d0959460945e3e90b4307818be6de99135a4b225ec
+S = 33d2c45a355afbb8eb5f64fbdc4bd3719afbcba36d5d4bbc697887ecb7e7ecaf99bb31798977e3385544fd4c44efe1b05f2a34119bafcd6377c24f57c030498f6d96148677079ffa05a253e9499d6b13d3c02d5347dd3263045919f1a7169f4297cb4ead2340e6706269a8607b1575044e75adcb94cc7db8ed80a776ff1e56d1ac13ed7d82439750d51904337c63bea9a059a056f30bbb8c1c721a0d666cb843b1a8223b197a9f48e3941a9f6d8cf022dc4edca612d057b2548986698f2a53266f49e7995640eebe929fceda0d33eb24437113edaea93e8d7892ab14b25e851b88808b470a90bdcff021e798ffbed003b3b9c8d53e4a1cf77aa7b5016a2ca41d4da22ebe498c73bb3d0239cf41ef7f404fd609d390c8c1a0d2f0a6817cd3ef966196d64c89524032b6ddfdc6f9d6876d6b9e1c55010969238af5f2ab616bbc9234445d07f2462aa907b31a08677fcb9236206187e00888b53e925c334f4993d3f18ad6db81ced54b666fc6513da7a4e8a8f1c0eaeb6819cce7cbd27de9f9c9718d900297247e41a704b7613221fa114cf145a1cdabf4217eee25678a24420c4a75f8d444069c976ef95d61e5abed512c01cff4b864038ec8e4aa877ac501664d48be5aba39a35df9b3b1ef01a25ebede122b1797494442420e0f0d0d4b7c49d85f9ffdb102a7a1e0ce6e4a99d9690a80958ed548e5beadec583c192316fc7311
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = e0dd55521da6bd181813a02ed22eb20e2f5d9070573846be5d9814c91ff072ba6de1514b6d08a4373d1b1feedb343e8e426c8a0fd6ac18bd02c052ec20adf9e799456b294df822d035ed7e4e4652c46299f06647ca02852b9e47b4e2e856ffdcad322c54861e40cb46b245b5dd2f4b727c10ad7ffae195ee7754c2133f928981
+S = 2c89c5c5b481ae5b632c628ac42501f9df48347c2ffdc7d06526d2884bd5dfa01591a0a197bc87c0c3e2b9fbd6934a29fe5039fcf5b5fc89c1731fda7e274e706826740dc352d95c470ec799bf4123e7d673060de89d217acc23ae544ef70e4bcff3af691123216582b4fb6bc277a1c364acd0bc7a689de95e2a90d762ef4ce7284ae0a9d42f0ff37a2f6a40da956cb08ef0520df1e5c9462ebb5694d93ab5ea7ab7cb3f1812eb06ffda74f651d15439797ee0597fd00c5c08ff08ceff35a44875afd485126a9044c0635c4ec60992dbeb9cb9be19541b019a270c85e2c7a31a687f96f13b75a11e1cccc0257a7a9baf665553ffd34802aa23f0db466ec35d8d5a0d6a560c75b0ed1f434ce06e23ea582e53851c59824e476686d027810f7b46f31e88969b8274bb3116277ec1a3982f26d6918d4919b2fbbd161af81786842b57c9dd7f388323dc377aa64dac6782abbac9ab3558cfa8c989b8df8ac5be897c848cfe00407ffc9de8f3dc94a263182523c31efac84120c3262158d9190908479fcf24343192b86991a15a2fbea0ed8ba12d7644af798be3205538ce4e45a437e116a1faaf527614e57a4fe2299c383fa2383a57b7e950eee956dfaad4dec984a239fa4e09586113659126658581b62de9eedda4a921589b02d2f24c57f2827b4044b8709bd688a8a114fc9c875973ef145ca1211698bde58ad273c67b6a5c44
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 22b5d51cc4048a5a3188dff7caabe8c2f2d8b59fcd3032da477f4cbb596e555b88faaab5ae249300fcea6a3d4077000c64973cc3376d05c171686200f173e0ea486c356e7bd8225205d59ecb1c4f304b35779d9aca71c3285b4dc5a2b33968c36cf5bd6db58701f8532fc1cae69d41276e621f4b0da534b60f17bbc82729b58d
+S = 297bb0df8a838904aab3f7a517cc87b6f5f4e53e314a2f6d0270fc34ec94da9341cf86aa8f7de3220485f0598a5907ac559e89bbbb1e6ce4fa2f1a17cb5c8696bbce34480ca4f7b2bfa2d446e028359fdeb265af0e3e1bf3232712cd06ae681d7c5e8107fd9b088931ec27893a0f2ec6b1b9a1e53e0da9a3e19a2bc840366acb9452099fe221f28a6a8913f2d866d3d0d4127ec3a96c71099e5ec63be473390c4aeb9cfec8a651e812807bf8b3dcf75fad8372382f86556924ab57dcfd59a02b9f3b2da272c1c738fa6f1fc3a78cdeaa91120cce66b9b3287037c1858645e418fa74a5ad75196e0d10d38052cd4ab8e5aba58805b4bd58daae20a801491d042180019cd41b70559fd9dbd1cb505c7f7feac497405697866753a8d3e2a92f854a988a50f3554ea0aab86e79d5516db5f729cfd4e2d1c7bc754d00d75de863dbc5c254748e805da04492ff230aaa89ecee80b5501128bc37646fee92c3714e26fda4a120f684dfc043bc26cba3347a3defceedf425e729ebc0f7199a348f29e500a0cf50bbc71375b0c7324f41db18f7e3091c9435f3238ca879e61684ec7c5e05ceb3835d4a3efa4d07ab918a4c0b10f01fc8207e15aeab15d21fdf032960fe5235447bd5c6eddda747e8d9e11c3d05612ca1491cc5d1314946e45e3aa1c6b1756dc906168684685133375a7d7cb69ab04eab56cbba728e70ae8d4deccf4139a7
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 709fa24119653806778374d1d9574c92fef4959886c61958a97ae96a2918f5d48572d98b70c2fa37818fd2372cd088e5f154c41bd361c1f60c9ca4d9ff280cb56e12ea88eded932497b91332ff0ac4766a6620553beed494ae401562c99d379990477c41792d2a561fcae0ca3a4b29cecff0524ea4b479baf730e70c6fbda007
+S = 0b7c22e20bb685bcd1d871bd2466cbf02994e50238895ac17cb51bc630b646f3ccf7d1c572478d762648e958e8fe1cc1d6a3b5eb6ce85bef9a01945cfe9755cf2d55875ed9cc0b1980e54d9d11a64a4855fccfaa3c3f4973bea94717b18bc4960734bce689a6581061a85e6a6e316540d209e6044c5bee56fbde7319716094ebf240133b1c2dab38565846f0603efc68ba43c36f439f49f8ad9110833156a72435948c3581c2d5bc1dd40441a5d63200252cc9e8af7bad81f5513313ac3c3665a03cf2d89c98b736d3ae566a175a979885d4d1bc87913eb1c755de17d2c80bf91baa108027af75e55ef8c5f13d26b4ff88ba3fc4b9aabfb36f90927678a2838e374eb764a3773d769ecfe9fbee806b30d3b1828fa1aa8a082563ce38279f26c09b898ee863e5eaa868d9a52a35612cbc5e87e5202d5f1fe6608e0d20ffa9641588a8e60cd0f06b8455f72378ec5e75015b4e3933c3a8d8c72e204db29e3327f8d3c30f8b9150760673b572c0a1af15b0344ffc3e5d405a208fb96b2f8f03c63806351ae34108dd8f9018a6220c67d962c76fb09579bea1c43121d467e05684f267d7633caa14cec7c81fce053aa121922c190f042bbcb08e37dffc6b7f7e022fe9c937882c27fd8b4e8002a53efd9e7c32cdbee30b373bd40d547c07696b3e854e4fa66b4fd7b9ef41b8f6ca5e6e7acea19e6e624d61e24494bd93ae7226d686
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 6b9b00a0420a1869f6fe4de18f707dfa850983b626efba9737dfbd56de7c71d8c0e6465d668fb9fbe54a1e4bbea59c6203797902bbbf971288a53f4c87e21e3678468d531f95169ae9953327d36658318812343cc965358f12ff4ae97ba7ec70dce25fea34c4352f4c0715de975aba505dfb3eca188899f71f1365958174e46e
+S = 7b08a6191987f3def583b16c365017b9a9f4baa76826ef12593e448fd5d7cc49d441fe7ac0edee5dbd1685a7295a724bc0b1137e8860930f12bdda8527b60c3ab08546d887f77e74315d4a6be9d4531413914645d51c05008a7e145257af7e7a1e41d949f284be7a7f1ac71885275da46ad75b45d6f19785f0a7a4f18124eb8b2d3692ca9d7c3b2cd05fe1df60ebebeff90cdb7b18b20a704acf64407de123a553cbf21c2468a25595fe2e2f6c0516221efb0f5057d92d0e64e0d95c1e5500467fe7c1742561fd0ed03fdbe4795a9a7457c3eba1033e11af6ae64e59bb9c84412fe89551d52435bb0b717cfb8b029413ea796f6b69212649c97e5a7f2e2ac50eff7b1485a251154c6da8609765e3e3b5cc155f0316c0f8a3f6630177a881e3546ba1dfa404430a0910f71531b892c6964abe8cfddadf60a301427d9d43bd8bfffcc68ddbb1df8b718f07ef794d95f47650b0608c5e5beef2edd339021152c5cd33d6737ff3c5f5aff14ef447274a7cd727e4f9530e40470989e60e0849eb3eec1a124feac7b452dcb5ff002225bbacb420a60afeb10781e7784140aad0f76b01b00343835caff44983b0e681154478b951845cd26b852f279ea45f4f6887ba29976c48fc618a7eee9b7b110fc00f495f015264ac6e0e88ae0129748da755264ee4b1289882a1cbff971d6e87545cd670875c0ebf2464f1133ba5ef764d49cb98
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a0500041427b561ce228f7d5f0f8a9b1a35af930ab5a9cfa6efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = dbee53378324652b696ae9daee6d6ceb27bbd30533cb49efcc3e7cf51b64098ed102343d7352ddb5f54cb0408b249b61bc1485b8b85b3d27eb86b033d2ee60ad0e821191b7c6c52ef21ceb87c643d4fa2b1d661f64b514f38f800e367be3b411b9f651fcf68806df8863047746d0fefc9d5edf01e0e0b89be0b5fcc5bd4cef03
+S = 24d07b55df196ab4f27c5c1008b49b54d726af278fad7408c8006262756037498841b35db44ea4ef7514a1edb148da8ef08fef64ee14c3059e6983526acfa9e6e64af6e056e0e6a602c9656253829adf8bdd43950885e3a6a8f202d90a728e0377242fa09cd3de5108b8b06b44d968f10e3652cd8840daac895b08923b981ad4ae2bf4ecbd230afb18c1fbd645eb993b40ba4e0aecee894d76bb414e33c1ed752abc8c8d950b4a16868337b40dbcd9707b3c28b5d59dfbfbce57dbcb54238f86fc7ce2c6a5386388a73da4e65c5b2a48d620819760a6f64b34cea861fa0703bbcb80524c63ff64c673250e1cd922cc3fdce9849e9c57fdbf3312c2f5517abd501ee26bb06e7ee25e58b3051944e0e47e6074a9af1f6e6ab3879057eb82519521856dc94e70e4b8663d8e2af2064b75847cf02d814a77a64bd395cc1f3357ae466f4d9ffb5f0b808d770b854ea44295984a938337729d301f28bbc5e332e27dc023c96db9bef26664d4a3d10993fd6942372254ec5639ed69905eee6b6afb2bda04685d34e3d1e7e1b8fabf9fc1a0418623c014e27b9acf277097108cbccec1be5527e7baa2ab100d8ad16ad1046f84e728ad3daa98a681c7cbd520d1ef131dd5d588325b390ff12e7b565c04de481c03dbb16f24f96a9241437ad31aefeb336ff3a1669aecf15302b26528f90b0ccb1853881d89318edbf3929ec5bc45ad5cc8
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a050004149f14ee6f6cd3ed793d7fa5a7dceafe71ee86f6c6
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 1d9f5b7a9786d2d493b4277ed95816559e6521ea07fa308deb217baadbbda9595fbe39308397225b92f2b6ef22a2cc7c50d91ee24d9bf0651a72f3038f646804a22288d4e682240e522f89d9449fa677c546711b0f0a86fb4df611a7a132ef996b33100dc92f20135ad466e24839ec6f8515e03e542f3a780c159f3f1811853e
+S = 287a3784de71ed88e4621273a477d5570a0db6dd00d528ae7378858a01e7412a6ed335f30e0b4672d61a6f248ddfcf40ac8d827f847355fb0751e4ba40ecfcb9373a0439200778ce27391480c21938515d174db382e27d57148fd235b7663b9d4bd4b1f8bf1134900bccc5a0dd53bbac5336363d8976e01804b9cd089700fbe7ac7bf61f511e8fc3d0cd28f6e6207ef9d5757b762ee96facb746d7c514526b5c6afc71879e359130bbbde3110b9fd1d35c2c4be5a0246a53b164b3c6b5ebc96f10657d2faa629bbff44cdab4fb9aef359251f3b7e33d96bc96caa65a4ce7ca31ce65be880560469712de61585c59c3513bbe87dca0076670b142fb8e6e65b18f21ed0d931a1712a4c6d62cdb6411626d70593e97716b22d10d3bfb6420f8471e6c75509f6495bc1505a8bf8172512cc20dc76875d3adec3a29dd7fe79e258344e8cd8094520d1e4e07e20092e5a4dfdecc30625e9547b23c6a27abc6dc058a2e51f769f6a232fbd09577da3a137401cd1c6e4c7ae959a52fdcf1f7aa4856db6e58fff070e20becbb735dcc3c7a2208ad7cef837891d20281e2045d47a37ab9e7eef5234de2d0e9e5c33b48bf8d9475f96fa368a87cd3bb82b0ef167f5533ed365e73b8e64657dc9c616794d4508042bf5b727d60cfdbc4999e8429d02ef91156cc74942fc08e85a9e08630887dfa4d820bc90c96eaea99af4b6c90beca889fe2
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = a96a3d33f00d283002fe250940244a11048a4bbd3c6d3d5858939ff767de9ab07c2088075731b4a9413f605d38660d374c80f60e493fde3196790b565dc293d3ec40d6115cbb4c3d70f48140bf385df21634a98a180bcf5a27a6e1b9884cdd40c172303946d4785455c48e9c1fc2c4aa284e6b18f0fa9939d3c329072ea1025d
+S = 553b659961b3c76e6ae1f2cc56928e90488c5a6c8c8f6be7885824cd69730b356a57a42f7da21ee061bbdf8354a6ffb3b4c96948a7547c77e6786afd77bd6507aa159919d0eb56384610a18a971c396f994cb6f2b426fcb0b96a12836ae99f6f1e91de39a90c6df4e88af34dd59ece75f1d841466eb72634ae73fb66b952e4a7f071f09777033faf0bfae8fe80d7b45c3e46b063c06adaa71ea66e8bace380d35fc8dc3d61cc4687655b89f2a74a41f29f8ea4b77a806a0239bff08c596392e5a78472af3cbba23bcf8145ab3cabc66d04bab15a8330cbd6f626673fd16c8a30a6c4eb110690e2d5bcddb327619887a12475e0d598866123b2604e3d14750e5593276e3830f11cbaa30f7ee61479ee05788f1f7616053b98599bb5246261de3e90df969d0f84dc41066305ca493e5c814cd199590e6ee20317ad9acea9ec22b57185d334c17855485edcc3d2d7e939800c12d02b4bf818c72bc03d9d06c228aebbe9dc7d018349fc9ed8ad34249e05a99cecf3dfff0e2061af2e6357518758b1ce23db5bb2d69fe5fbe64b3e08b193c30c647233a60372e64cb550f90a923321cec4ec692b3d2caadab37b6fb3826d591449ae2ca3a6a754df669f3a5beda1b191a8a2107c649d69234d83ceab0a1c0f65bbb9d7f518a0106c655b86b3a280dfc8c75548612b01bad47e7b1c232a0af34e7de7291eb9e747292e78b61fa0c174
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = cb9fd0e59bc6d0c1b1ca328db6bd9205ca50ab8526e81dc000f46eb5af7d4edf10fe1fac2877b4310bbd591cfc1414ead5ff2b5aaa57e621a99b96df4487d65293e811c9f3ae45dcf443065b721bc584018d52798fe1a0f144aac92dad56512e1a03af254494092b330440325ffb2c3b169f29ca1dadd2979ac80c87311147da
+S = 7a0a3a76ee0fd8be7ab380c909d18702fb0ee2730c61bdb7fe5623fe62137145bd555dd1945ace3c46888afa725359bfa21028dbcec113d14948a95a3ef8fde2a454d56627de249a7548306ca4c042037ec8ded524926237d69bd4099383e0fe68cbfa1d13542955aeca3fb27e1c21dbec1f6b763c0e5df2efb9e3b0a5a5ee439c91832361f27237f7570e0fbe93ccaba416a2495daa38a7adc15c5f39ceaeeb9240ef19e6e58a07567fa3d8fe5cc375ba28d15395a8afe98b71162609a06ae34035f6e92e7e58c6e814aa9714880fc8403bef091396ea465bdede70706e514431ece1a30b6b0e640456a3c353a790b5e9fcd1a75177aaa092af6cb07221df11b9dfd9f9e7be02b2433841cb7e3db33a5e4010b0c411e7c823af510c80c5930279b7f655c52d7abe24050561c5ea2f290a8e59d17ed8f7873446ac329095814b47d2710648090aa52b4e969298968e313f7f7e49599bb01fe361e1d16ff10d25eab366ea47aed18c98fb87c1ff915bf040db4a46458e12173823e541a47f7fa92377db3070cca6ffb9b78e36fb90fd662f47605b8872b8556c886b84a774dce72f92f8f673f55f8bf24153c9f18753ebae13d999ddb8caa25fc75ec58f29adff866dd5ea68aaee641d9e34c3783187c3383f57a88ef1b72e90ff9f512a6061ba922954f63cbc0726b2935adee477a14e6b38e7115be26b314e456c65d56b3a07
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 0bdae31979864502cc9e0cc38b9d97ccb0aa40a0076de142d72197e9c4eac5fbf4695c39718e5a37ceae91100ed6aa57c15e695170c133613baccdc3c154667d400dd893fd192b7be7bd5ad0779a5a4bda3b59ee52eb4482dac98b44091e28dc38edde8ee7ccbeb45df3f06c8f93b08e436997e175921c8efaa15ad463ef14fe
+S = 34a41f46718ae045c386405e56268514a7baa1fe63c6a4e1c963b1a43010720caee088df14f3ae4681a5a63f89966ba2ec3243fdb80514a977004680770bc8e7069acc7aab3130532064a74f14e86356708f32829ca06e0749af4c6fd8210e2137bfacd11087630828afc4a15d01f8bc1c1a59eee3b6815e4168017dd572136af46860d0ec0d8b24d342d8502c09528fe02ca39c78daa7eb6c6ab0d9f063d92338f68aa7b165b05d044e7f9cb9ba1f059058c15b088a3087d6797658523b3f3950ff37c7fe135886b0b309b5e3d259993e1373e7c86626497c573264d928ec0c3d653cbee9403f12de12c7790c54e0bed9cbbe70aa78094972bd921cd0dfed81ea6e91df914e83e75dbc714eb89e7dcf3dd4d71450424898133a9bc67bd4e103422cbea4adac473efb16c6b10ebe089ee60034e0c599f66f836574f7207180cd6de83e3708128d867439a90748676fee209dec01acd90d5003fcf7dd1e919bbb3ace60cad0964081a8eaed261c5eddc7384297731cf9cf892730b938e8aeeedd60b06617fe7639c2f3493bf96cff12df30b19ae86c8edb0867f5476b6c381301ba9cd3ccd39b12ba11222068878550cda07e217185eea14f75bc44512490d1aefa18ed11729867e4e16eab49770747cdca5d4c39b451d50ac9432c42bf3122da7472fd58d95ce0937d33818449ece98b64ab39d1d0e0ed5e6ac11f5b119dec8f
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c0b8e0726c9d9bb66179c5fbffb9b336ce88a54e819789583af5fface
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 0f46bac55d9e2d3bcf07f70ffccc050fc35fd35232a87629a69de0533413607048d368b88cf193ed0c59e68e97ab574e68498bc506aee4646801bbae5de9eaa52ba48e8376530bab649850dfff635cb3db090042f897e71fe965d58f36ee2cf500deb48de36d9b5d21ecbb69fc9d1c2763c8ba32d10b884273f2b45c89c82d46
+S = 5ac96146da56064477b2994f953f31906fb9f546553551c4c76b4811074194dd0a4622e3a53e6c9d13404dae87e4f13b7142bea20336ee033295f2ed94405d7ec0351d880c78d753ca18dcb6b39735c588e656aceae827c273068097b39d1567f921a4f2305f7543fe2efeb0ec47a0dba7849ba4e919c388cf05de325c2399cf84f1a167a0895a783e167732020826d5735e8b0b7cba4ee338ff586cde712eaf638e7163ba45ef94818f73e7b7160243ac366dce1730b9ac0937532607f9d5f24f9fdb1e227150d0df91a8ebd951e7aacb371c0ed053c204b22735ed7688d587cba4a23f7857d05fdf97cce9f363389832c35ad291757c0ff8ff1e5a5075aa97856cff7838d3ecda3450a7c9d27f0617ec80c94a2e2a09028fca6e613f902399ef4f783e768f8f62e097a2dc52dbe096bab99cc4d01ca7020d72d0566cd6b8b0df6c1a1123247097b8ecd978925a540e05c2acd9d65d3e64a6b05702824380c1a24bd67d66f2b623f962e89087f08c5695b3f9655fdf24856a9f6561f4191ac338d67e90bc0c747ef7cd5a115d47aaa9d048ebc84c098383260fee49bdb446d1a153e51b0041a5e34bf71ef2d9b579067138a492e6ac8a693da58d5ff37743de28411d56090ee31f9e08cfb8566c7067635a30ed65cc24d40e1084d6c4164740d0770a88a287897b34fc4490a7f565827d8139577c0052f4760ef17c5f5978a3
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041ce07ae5bb44ac73b9490d62cb7f02d236e95b023c7aba070143c6243cefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = ec287cdb5ee54e8441dcc0662f98420233406c61c6bd9255fd1f9701003d069bbe9c5e71df93ae2afaac624f094c5d0a1a97482d478e2975e77a3711068eed5e13c85df5d918c7e7b1c46a47f50b9ae9b709136ab3da8d7083029033120c8a3d53721f6e33bdc042cced7f57db1b2129745d7520f4eae5ce387f4b710c0106c0
+S = 30a67f084b071c9e0d5c5f3f797cd89441932da1e5cf9b7788855d03f6f2a52d6519ae67ea7616d76f2a73016dec5663f6e337c9c26ab3a4e0bb6d3f8ea18d0ebb1693ca5419b9cd19fe747f486f8bdc40164da9d7024d7fc675b7f87b702615ba523b59a747550a26bdb8a80a57dd14698a17b6ed4c4f04fbcb3ad98a2190f02f508b681a517663a3c0a4516f92f87cd9077b674e716099e36dc50ad24f98bb74a6afd0f85318a67abdab02fa2853d206acf49f941706cdb0e632244f2be99ca1aa9cf36f2383c1092371031a99b7342714fffffbbac48ebe8fc7a1f31c40834090d7dd9d905047ec08aa0c73d1b2a3cdf6c10d3930db3f8675a97ec1cb175142725bdce1d73dc97f656ac1441c967475e46b7a94ed38d067def9a54bfaeca15a49780f5caf2e42ad3b5df0787c1c06844b28b68dfb0d675e235a4114920e327e870e2346572c3b04aa29ec476933470a0e56fdf3ec0f5e1baa35265637cad3b24de388eb4b68403b4b6652ac1c258cc56bc4cd9d3d804632da9eb23445154fbf26d2eefa30ec2916a54b052ce58baddf426680477aabbee34fc6d98e57af4342b2942c77dd8695103487203a77d4f8e4ee066bf003f45cdcabe7b57b46b34084bf22eb5c905ac76df823a0e9343fbe4a868a6e0adb58bb5725b8da3c03933d95b4012498557bb78d096b810be5f403b9063243bbec780de51ce927d7294ff4
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = c9228bd9823d98cc91944bd362aba13e16f6cfc78d9fea74c383e8be607ec7f28ae80cd8fe5f6f935fc7d5c8cd907e02ba378055f910744218426fdbf01334277a66a7c8e58185dbe51453204d77945be0343ffa64c570f7f99f5e00a96f8dd640a345f35e2c426fca82ad2409e94b1130f4f5fcf647485b0da09d75b3193bc5
+S = 7ddff91ff1168c9bf0843a1da3c141e1856e312c0d83c4052b9c134d3b0fa82a53e4e1923b051be39fb6245d6acda63026161feed4e2d56d83677ebb347b1849d479b3da628b02a3a411f86c443e7807f6b5239950bf2b060da1c6905dc75ec2e4236b8cdd77419361abd4720267ce447c104f437afab32af9e1b4c0104989ebefbaa7ec0c18a065a0c38a79ccd9e40eac3554d78f3dafdce7acf06e19e7e2792cd7c70bf1f0eb15e32c7d6c41331ad8c8a1bd70d4bf74e64548175d913999aa673c995bbe8ae3e68c362e3427c116290a9680d6d7b4be07de3cdeac0a0723699be8ad032f794610510ec4f61eaf355e56e15d053007b1d228a91b1f576597c1c78636c2202ff55c070eb3242b48eada77b90777001067fe61907ebccce40bb6b6361add71717c3a429267147b341bfa8bf0400512c538948a9171f2d0aa278aef5b950b5b7722b372ed5c2ba1e18562f0fd7b7da7566f61f5adf1f8ed1023605f360872cd963286bb5685cfda4968f412922df0b9b7cd0ffd8dbd16a2382b6893b4d075bd0965f4f7e4e2c09b0bd00217fa6bcf9e0ac71309e071c4ca0077bcca9c60ee5226ef058ff8b7a076d68cf161b13dc90d51f65babe1f4727396f070af6b3dce92586e0d31028e6adcfcbc32c71551c7d688cf9c32fbb26d03c5fabd455fc716d9a9cb82a740a6a46627d80c75035b0bf02dac08ed6f45539f035885
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 91e945fbaa97924f3e6d9ad222bb01e935b7b41df0c2207a3eeca2348eb93e9127269302bce70e9341f35f86fd42293bdfd5fe5415f88a16dbc40e1191e7110311a852fa3f2500b9e2df2d5db2798140b1bd2b1ebfe01d76690779330309468cf67768295adacf87c83bee9d69e96fc0537625c41603426491bdcae30ba847f4
+S = 34dd79f3254da1471173aff6aaf54ec5a8633b468af99d925ec258438f3bade74fd1f23c631f94e6db57b3fec9b05ffb18013cc090bcb1f871e011241b352549e9dc72349681c10bdeb1ef00f99d4a70c48488d812bb621d0e3b926876b91da56541176dcea55152d31915f9e633620886f6264c70c2875019afd51eea4ac8cafc17842e2e035233d4679cb22d329a671b061a2da194d00dfe6a3d6ea3c3b10369e0558b68456b241e7c368e2492bd0d5cbbdab42a8526acc04cf2ed43944708e99980b31bdac37e754850c0370da4ac8b71b5147ddc91dcb7509df44b3fad89c2cb4e147255b064ffa9ff758a55c045f27bdb4b12107e1820530431a28baa16da02925ffc8e84cbc7ecf70c2dab46e246ac51888a198d85dbbdf4be40e674e562533667240e043a6e8a7d1a026af2ecf6a1cd24934f6469e28b14bea0f46cd333b1043d837b5b21022c9f7dd7713f8576152431746b54c9cb9a7ed3bb5c7d027281cbdf9377187fd584b8761f5f6972ef357cf8c54c9009d9e650aeb4c9d718919706d48ac76c404875e95d60b5cfc06588e1bef0ae95c31d13a27edb86dfb643d9d2f08373d7af39783804123202f796b1a01da28932a103a817c368f9e8bc8764cb949e351e0cfeac9087eca02e097662020927940b84dce30f22eb053c02f6345f6de59c2428a0c462020650db4e93c515304bd6fdfbf882d29034fe218c
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420a20a34a9c3d9d0e915b9f010007a3c625bf71d96211c68cee82075ad2dfd21e7efefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = c63bd2db43b2e094aeeb020514d2439f6d8d04d0c40b403398e0140481507ed617a965880fd7d975a7329deb459ae2df5ac656de8dd95d4716369eb86796c2c6125878f1e718bdd65c825aa73368aed95613ad1c06d7299034ea51362f7777a580ed16fe129d13219784432126652ef6291c1272762e2b77bca43266211a24da
+S = 18fe9f7495370f1b1a8318e33ef759e72fd463d358de45d4aa412b1c149607681d12d7da6b7640ff21b53745387e6a5c9effca633c0c6d1e7c150ac6b622981167fad90fdef6b0bc71bf87cf7aaff12afeb60c823d95b32e29f84fe500248207d792d27965f915cd9527a666985223b4b2e7d72b1819cea49c825c304eec56632188b0907b54e2fd9d805a53e58acd08b291532d9500c64ff406d54c0f43e16c5a6f40499d20383e6537bda582b5081d0db95bead3b436c7d12d5c9ac695d4b660c79feafaee8b79f4fd9147cb5a14f5c8700c868d24bf0bd086397deee79284b3a79e9b68560ed6e863da75da37d324edf13243556f66982745b2ae931e3f2348fd8c3f206b183cd8768183c92ce6a0daccaface91f3ad6dda20d5c604b5c474918fb124c494f76d68ca7192ef25bca03648eae43008f9c3482bdb7b086ea92d41ba3a243bba037f7f08dfc6912218dca0fb97a11acd0ec3432d1fa4fd73f4d810843606374c780b8fef34ec13fa6e26ca05124d8029cf7ee6f9cc90ddc1196e29c4a6ec9feaca4c2050053a212838ab901bb9df01e31b6519a9d4f019ae5bebe1bcafc92f79ec70bb1e1f1db62cd964b8a15171edc72081daf239b0f9306921444032295b4c7428873e142fd20ed2f2e598fa346f2a76579045c727de99294e2245db6d62061d1a2cae226f0aade7da4bc32fc6e750483cc20fb2f017178be
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = d34ec8c4045b0433954c81096a09dc82a0c6c799157bac1d2a949407c7ea480ba0f3b56db735951622014ce70f5d104d05424d166d084883501e029e62fe5fcd406087a8f6ae8d08c4b94f6022aa9d51013b9d7854276d8bcfde0ba4ee7e72dc3aff061cc8ad323002dc501da9d7c9b51b197d68d2c0655d2e3e76c27452c960
+S = 4082a6bb4453970119c7f4cd61253f441fba30c004ddda4ef25f6b9f30edfd3d2db0f207e8b7c34f2d9ee23d692c850a29e70906a98fabdfebb5fac91722dbab0f19ea0b3952041cc448fa9e3eb8b54965e068a2a0df68b44f2839b9d10ed07f9d92039772bf6fe6a6d4db2531a03d7eebc15a125b87ec9899cf7b14911dcc4f0880b2196e165c1e45edc0de4abf859f30d87e3bfc3cbd69ed066aeef26869ec70012f0c1d1e13ba1bed0a6260d0c412c8e4aa6fd0f8b716ce33fc5bbf3562e98c307b1b8e617b26aa3f55e3dc063f7ffe4d03844b0da97411f3996fd94416648724148bffc5900f1f9b908f2c6ff5ad20c90d3f5ebd76e3aadab7b9e9e55ef50ecf4d923249a83cc59167e65bf6593aeeccd750ef0c3f1029dae3fe1ee23678ea70406a4e4f9f1165a48c16659d367e2f1748e104ed1f898db701336c680400818cebb47529fcd1f9da787a025c316a2baf2c1d32eba2eab393830eee7a2465d0e43c19362e64266883be22d85a0efa83f3f837d206bfc96993d16199712f6947b39cf0875b3744d96705ea19c8a173aeba23c6a049aa668a66f2c6559cba601c4a8737fe512509e90eb5751abe5c45f22e9fe31dc936b7e80544daa4e26cb9d088a623ad6a7e70902196a0973b8bae0866513360a05265ba92e96fd8e7a09e35a239a0d2499713ca0e7b5dabb06d162fac90a75e9b6483b3513787b66b9f85
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d0609608648016503040201050004206befb2ccaf4b531cf9ffc53f938035025cfdb7eeae29da84ebec94e716c003f8
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 8f937d50d24a1a6ed858d2e3de56e5c23b917d5a936c87b84effc06d48041391caf42207ba6d23030ed7edca864752b99ba3b089b308c3d19668bdcc2578995d4ac9ac502b347de3a37cd685f22f1bddb3cddb0e0f2ca53a311b1d45f9464edbf55a42b48d69d0167d8fb69c89d6e8376b57277211a2d4fa0560075d2d37dc12
+S = 2df1e58e7491739bb027c6315a70eebbcf37b8e5958df07578a589a47cbaf1edb23ff2e676f2f273a1cc0babd22e0bff874529cfd6479ae5c7250f06579eb212dd3f4058c476abae8e94c89afe05746c3aea93155cf03195ce5f4eced399d2b61aab7f4060b69844cbff6303d264c4755be78af001d125af461fececad8f46a9c4b07420ca63c4212f80a751fcca6a4737684543fcf07b39089baa9995394766f69239479e7c9778c644e022dd4ec7e07a769aa75db2571e58a5e0ba1e4377e9677092bc9dee9d9dbb448441da8f4385b4d4f8ccff4b3dc3c3c3ac8ba11a6ce8caafa930108ba3603c5b0ef65a02a7afebebf605aa88511513a69b3086fdfc25c588c4d61a06219d0d5643410d3ae4d78b2f695efe4e0b82161c53bb9d4b8a83692bb16de8da18b4a6c2abbd0f6b0e24229077fd6c3bca918bc9d9f4518598238df0c925f8587fff0852c44e8107ccbc1ce6a9be3b0941c3b28bb03c87eeb959d719dba9a64a338c7b9931cdf6bb169686de1f8de0e1fa74d03419d164f2c8bd2030562705d1470415e48144181dfd31cdd4219b5d22f9a4c659923cf5c4edbde18e8277dae11264c11423c5481402e80af223f0c4faea0c2c7aefacbf513962c2f16af353ffae1414b408f726eeb946d7c4c8577e72d8f1d49ae2301cf70abee46d286a6fac1b888c334538abb3b830fae595bbb19ea9dce46a343da031117c
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = ef737d90f65532a2693ef41fe916a2b970c411409d3801c54caf50ff6a326eee086011bdad6e2aedf16c17b047ca1a931b1a0a601d174843dce7f52b969d62734e02c8c220953a30d2d0d7aaabad449788695abb2c881b5cd819eba41b3bfd47ece00b66f6d14ab233f39dd4bcc8080de03868197392625a68ce9a32a31525b1
+S = 6d2d3c16eed39f5b46ffc45a8476c0778bda78d2dfd246ebcfbc74f88c5ab742cab942de2da36e1ec2cf65a43b4ff04927021211b35d6b6b2136ef1d69671aa8b95f6b55be4751a54b8df1bd87518e4a736bff9ef849cf7bc212734b77a7fcfd3ba99327884685a146294ba0a45233b03e97a27af2f615952261cbfdb1b5bac0f5fadbb8decbc4b16ac96606242a9489f20fa74f726d3c45e0e0c515382288a8ac19ccd3eec7ac94d30019dcbfbf77f9dd592531eb1ef4eacf9c38ccc0414317a3d7eecbac02a130b8bfda18f4e0fa6a5bcab44d35e020afdfda351afa1f9feab93579861d2ac39e6c8499b8b5777a6be5ac77b3ecdb12fe8189b0bfc00a4a3e4e6041e2d52a5112e8af45e5d0a45f0b88ef66ca29076738ed07129be4493916bd885e128359e860ad8f0c0d8fb649710cc76a0d3ea701a2ba1d7e77ff9b037c51f93e9b9e162f71da900c07b42ce0f02fa633e8e987cd063b8659f25d190f3d35105f70edb65201dd67d9565cf4e718f4db2f57569c8c88f20ec11aae3ba3bc1bc78c29b2364acf2f964fd2165fe82d8721f1b16b668804468f0697643d1bd0efc5d45f8c27b7804b4931e210a1eb789c8422d7795a9b156fd9762a56fa27b7d5adb2357797ba50dea7ffd217025876ade111d504799ef8fec084e061ca0b884899701a9265969a9a027c5337cb0e1e86d3d5d1b8a0a80eda33c8936b436c83
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 5e59add32c339dd10f33de88b32b8cfc1dd8fe7684693e27633bbc0dcce7431bff7e2b943b13d1b8d47a44a286504171093b62a6e57392cd8882c4609648e5e880410e65580bfff0e422c99ff1efcaa9e901decaa89ad4e98c6d1ff9cba6ce1d0a2bbf0f2b210fc266b3d4469b0e0fede6b0dcac75e3ecc3968435a01409e801
+S = 5d7f2def0ab2f104974b66e6a7ed79a4cbe4d9c6ab4bed75f442703fdaecf0e76eef5fa5c13163b4fa661137c877e4416a3fbb4a15a2dd534267ab860ae73bb97abb5e48bd5ac60108baf4aa28eaa5b3aed8f84adf06063e575b39c932a565ac9689a6ea93359f5e5c384bd41af7627df06169ad4728e9b17f5cc7855b5e2a88d4417142bce9b45ffd82e785c6cc8774e3c78fa637ac69c90a2198909fb1b611ba28ec978b1813bfcedc2a4ab6f8a2f457a146be5a6ef6ef90a91caa3553f96a743ef0f3c2a057ffee3ea2b4a3a2c7e9b26ee2e531f8b17216080096527df06b83bc11ecb977053e5d81f6c3e30e0fc5d4353bcb7bd97906ae7eb4bb1670fe28a8bd674c836e395953d3c3e64503818e3c563284c7d21545e7038d3dffa0182b5e6a7ca50e07d7dbd3614c4b2006a4f1a14b77c3dabf98459cd33ec5b325118f9e65b851a155b3f73267950c92078c70fc5dff3e9f07a9c5ef42fc210b5d2b24a9dec7db05c12e492decaf4b448c9545ee492dc0c2a4a5bff2ed32a8a0ca0a41b7f7455e622763319054e1212c0297bb604452f82393a3a96f54b1a141da0edeef052d2f0382375e501d67b1a83d0b02bdd9c99fd68063b908da1738e88b2da99979abbf73e60a4a295d24fda59db64486bfd7eb5b8dab06dd22202d58422bd450f1f698d7ba51f71ef556c5bad3d1461481677e501dde5b613fb2ccf85fb40f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 655d108236ed81085d937f81dd9056d691a1dd531f2507f32a81b5dec9c4ce30388792fcce182b912fd785fbc3df60cd67e9a41e626ef4d29a0c851b082b313e69e0c79b3612a6e8d7db8abd1430a555ccc5f293e92bc643933ba8a3a4b862215c30586757231995bb6834cdb6cb4df528fb6fb89ca4a4ce7dd8c37e87b38a61
+S = 3363dc1b2f8be1f660baf2b61348786a7305f4bc3e7f030318a743893e41feb40636f768a286c0e82f0638eece2d7f53f8b5c8c5052e6a942e9a99fef85e8d5f2d83e6768515ca14c8e8dce14717af8fd5a2ef209c9b8bd314e5297eb48aabdb7875d1c33efbe9d18ef9021ec41cb54926bd3542243db8c576d8bcfc61b5dc6bc8f37b91e3d631bfed66d97e9a39aa815a8c138932d4b6087b5413c888e97caa07b54541f22cda57a9d06b92047276bd21bc5ed946650ce7f9b07cc2e150bf14233e8571a8f09259dc1620e6f55609b2f2a257dfe250649de5e7dc42fd7503809d0ca8344cc92571a91ca99abe1d22bb6f56e84ab0ccbbca0d8267fadf08017fe98ec57088234e81546386ea48725e0edffff0738ccc99aeff1f3977be58761373749175e7adb270ca322f15f866a668b3473f5587ca80fb61200acb3c09bbc087419a5d4a3408131571d06f09607f8d0b07a285b79d041842e5cbb682e11db41b0c36784c4c4895d007f076d3e3ed2a13d9f0601cd4e95ed492dd57505f76f119eb3fe56c899c20aa745335fa2df73552e95ae596b1ceb67e3a533b2df1ea1ed661fe5b46e1e31b753211eb44fe683e26fa1faee65adede0c86c788a067cd1c885ccbfc0066fa94070a310cdcd19003b6b7fc836c79f19e7e402a549850719c3cc3fb4cea67de4332680c3b891e0aa42693bf113fb7210e6b0d470d30335a69
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = ab8fbba0e6a56a02b0b42f139cd656416b9bb654da952b09bf1a46fd544542cdd33e3a7c43bb9a1591c7d491e2c354fa28aab5d1f39935ae8b8e66263b6f27f1ef4fd34c02eeb89d517ecb5694ad991beedf8127c2bb21ecc9ea0ef9611bc821284beddaca43ace317627d2a599c0fece4c3821eee05d70ca1b7a5406f510da5
+S = 87615e72a27b387de06e4e8bc3f2e70d24d061abb00a8a006456ff0b8bee03924307420517eccb0eee44c1f8a7458e13c0694c1bf7855d5ab1202807339bc82cb5cb3974b83d4000751fdced787295387acb814c2ffb4f636704de4595bf281d544f72d676bf59768389d92bbb08ad9662481129af3ea0ff2a0faadad65c93ab0029ee0ddff3ecd02e0bae13c4597de92cbddd6fcd9ba4d83688db7c278ca55e5c15b061993a1a53984efffc0ed72f55f79f3d11581ade9b651a6ddb5ad4863e3b9798d2bdd7c346174b114778f49ebde94c53c406ecc6812fec601995236ee09a8df5d0663ec4cb49fc47599b2b884cde458d6cba31abac1d3900fba8d9a053f02ceec3dc9f372b285634a3b21d4c7182c891523fc75bb8e49494d5f5eb4dd001c40fc549f9f586e60fd2f9b3b3dff4c8d33978193599de8471d2db11a4586f2be00c2f03d818ccee82f183f784c88a5d04e14ec99ef808e3e68333fefdaa414be5d7e817de3472ab212c40de7f172b3e62d203d7da871573f4f1fcd0f01f49258413e726cd91a79f465dc0ab69962436dcf52162c09fdbc151853327fe69a51ea91a339138742d555b40be06df4ddd594cc51baeac5738c96d0218363461bae49da0418fc3330adfd9ec008e89e2342a9084800893b2eb86e40e27da0500a171e234098079b91e08780d5d4e3308e5158bf7b4de557662311c533c9daf553a
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 450171e919ecc10bbf1d05f41eee02eab8eede088a31263433eb1652593d14b7494f7de1dd9fa465a39918283b6726d2010a9f80edaadcbab72afea43e007a782a44d633d006ad8f57e5f93219dd92254c61f187e2aa3a83ad4e7a7fc7142c9631070349bac9e371232a307880f94cc9e11b5b8532d94a78607e0f4bbe2232fb
+S = 0471456bd38ff2a5adeb19b73c35de60f07d7907479f9e6d5735dca75ebd3ef499194917287ae0c3334a5b97f2be41598917a5d880b3d021c61a7acfe9083441661f56fb984ec6717986c558a10d108fac9e00bbd5adbd817a7684edd424e612c8a7f60ff1c8056067f0eee1c6ce3a4ceb6c27c735f0fdc93cfb521b529e1002659e6fe9cddcc79c218a84ee59b7355a43b47b5c4ece8535e0874cca866e3981dec3d1996d4dd05afab27bb5dae9d6ac9dc39e957329eb273254c4e7784a29db26696bd0ff872eede9fff869c35487643755d9cd5bae01c7858b123e4f9688b1d2607f349d52c828dd6d76ff41514565564d39038814841a0441c232411c8afcb15073739f5d5c537138b9bbda60bfd2cfea2847678ffbab73eb02fcaba9e4cabd7768bc0c3a6009dd78f02a8d791f5e1e30d7358b5a642cf0a1a838b954b76a15386109926595b2862de80ddfea98e6218efb925cf5d6434b93045cad5bfd1af36e63a98c14b8f5c6974f04e5e52243bf7cffdc8cb9c0a35fc3250943d07037b319cafef02a2fd21c39aaa3da9f171f1e9c9613ff97d3a6770e7639ecbfa7e47804d8833e8212064d091e02801869bcb2bbbfc2be5d21b2da790ddd7973b6f5b9d6c763cfa503c6243851461490dfab31cccc6621fd91fc1ae28b4b1d393cb1e41d397852acd98fa35b93b6b4dd92e2d5fac7665d8c0b3f7d03ad3048b6854b
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 105048a958c92670205618120e4f1f5f40af63b03d2dc8272ba8c13743c8696683e3d051a21d92f149d4af1e803b9651674483ae26c40b4226d2f689826f4c33b86db227a589f7c9b0dbeb784570705b8535d35e3b165c771268232e0684265c19b5993347557d7ebb32742a4337d4060248fac7656de14f5833f32fb94f1e6a
+S = 82bd70e07ba8994dae47a4f8d639168e5e9aa2cf70cc3c011482d170efcaa8aae5d2c8e46d63a583c20d9b7ee21e39b86429aa4550c9f2df8a955a43e2ebd3ff99e1ff3625285de3d506a95e183c664374eaccf0ecfe6d1fdbdbd33f61696064815a21e43600fe7bd45830208970bd63eaff3d2d796740fe1917196bcdffa4107f6b143a7283dff052c1b732fbb545d2772fc725cb0f1f69689b57ea25a8e54c6d68bd10026b911134f034c9f9499f001c71e67a1668dcf11e3974c6ca2658a4dae79a103b1bc3e01195b8ca7da0a09923eabb8f7d035598383404fd7145946931cf2f577c3d2356aff6e2b37f4b084c00943de3c90b9f944f42af472a7eab05cb33d144ad0b36c2d3343f67af4c78bd1fa86b5dd66c9edbba788278dc063c2a6754c114ecbf5e12ce76ea97b9b83431f215f2670a5f23e27b1614330671d3f4b5701ac57bb8fc8a4eb33d2203d3a4faaa1513471d94446a6bf170a78389738567da8206f8e2a6d906a428253e7a2bd95b26ede968d6781b5247bdaa067988f671f9049da2fd3e81a9a0e419cf077d54d524fa561a395af3d443ef4e56f217fa5e981dd693999caa88da4a58bb7cf5bd0136ba939f507fca7ba93fb95c8e33837576230a28f2e66ae1c566f480b16f7f3c770128ffac3b2fa8dc33f1455f8178b1c4dde3d2df25c49d9d2458fcbc1c1c5c33dccda3987f50455f898609622063
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d0609608648016503040202050004303bcaa2105477a151f58e5854c43aea16ba8a3f7aec859c767b4c972f6516065230af636d2de691db4bf4eca0591d5df8
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = c74267ab7b27fc613890220c1b77f9205b8a8b4a7c8aa4f8c5f1e41bf5d7122b3216b36c42addb71fd6244de02ac9d72aacf24443a49774c5d6da726d14e8f1360de644112578d4ca1dab4042d561d7131ac3614b6117070c6b34ec9249fbb2c3ae2a1af53eeb7fa0a409b0602402025d869e94356a9376bea0bff8d5693407e
+S = 5daace94b6042b542d3ad0dbfd6987222d598febc1e612c89c008c8ae828767cb3248235febf65a100367753aa8c75445b08aca203a83d471b090c4b40eccf1a375e15e6db3cb49eab5db7bd30dd0ad2750ec9eeb09f1ca646f2cd7941cc53c1a5bd982032dad6c022f4958785fa37caed46c67fdb8fd0b8571494a255a0d8e093b79811b013e8bdd0636345c59fb31d1daef1ff7c8d777721cca8b5997cea173c2044ca0b0c552136ef57d5dbdc9383f034daaa20a61d6db7ba504d0ca67d9d3cc8df5c52603a870010d7024d7fc67ff2b719551ce5b1dcb3228c7c17b0772e3160ff940789935c563b72ad97302fbd276a7d17c8d6ac70866d945be4a19b3ed1256339c005a03c1bb0be9549d25a94daa4459ae2f6d3b2b4ebfddc545f76c3fd761016d3a4a79301c6d94d4f84ee9da965f1c9ef2239c6a7cdd28f4badb57580177b395fee7c684b70c43d92b5f5718e3353dda2ca34e10f0a1595474b3f0cfd90ffcd10c3ce987ed72da95aff0d967b582f9c7ba4067b77f728986bfa3fec94cca5104d361c185caaaa1daf8ae9a54553190d54e16c86604172cd53ff7b37060152d1fbc61e54817580aaa6a99ac1e577161c718c6810a735abf2cad04c51c901b26540e0546fe218be87b12929f2aacd48d9768c51d690820876b1a73bf3d8c86fbf3d37a0f2f8aa9f39dc8b86e3990001cb3ce8fe75d41ad863fa54acfb
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d06096086480165030402020500043041bc09c6fe8e745e4fbb2fa6312743e27bb5e82870600e0f80b1147e6ea9f392710548d938b910d106960f7d1989f8d0efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = c0af5d4f3251d02d37abc8770b5884391a66e7a1700087bc714a0280ca8d910fa794df3a27561b440cd54be9b845e49f5571981c535b701817221a54f12984db4f76aa883158acc8dd4d23a1d422b5f4045ce7ff3fd73325ecad5bf2fd59fc5a211d66413aa1ab4111dcf6a748371ebe91f07b511ebdf96b59b36a61d4652112
+S = 326963d3bb01390b62b4dc1326248ba0c0bc44b240e7b01fd5b05bb138777b31cec22ac0b0d53279ddeb14d86ef2acec7b0c3ba1c8e587513279ecfd6b912717d316ec7bb6aecd56004f9a110e3dafaf3f3f9997549e8b65751d1c4574dcf16a0df08ab705289a9b53930f2bf90c0a6a8f461c69d659929cc2b8514f6c08e07c0c542ec8bb2ab42512f48d8c866f4db4a309af0114e6b9ba1c382f48580a9befad7dbc1d9611de97fede893243fadd94dd78e99f43199d76ea3707d6c8a2e1339b534238bf1bcdf5c2b7144b616872c7a08d4d6399228d508d01c81e7dc345527ef087ccd983f94fccc1f5f8db9a34eee662484881f38eca79426ad87f4ad7ec35dc46c835ae5b38b8bdad63515d710eea32b8024558dc1929e704225debd4e9a770706c78057678199e4d006d185556f27bdfcf5330bbe9cde8271316f460efa53840dfaa30cc1f230395c4f12d7e0a0ae57d71297dcce3834a27b4f29a2c8381eeec3ef4e71a2b54ff1ee09147385f5e41fedb3c3df398cb53e1d19c97fc0f5f85f2fdd0b42cf2065fb68b7a2850e065016e9c3b88e4a0d17370cc63f771de00536c57739625372ec08d8241672ce3aac63dc843d17a227a7f6c68b85eb39e4074bd7ed49682242b213ceedada0db1f2ad978620c43aa88325284588a5244f82083c4420572e30486bd40902b71319c9b246ae9bd7d994f9396ff2bbe844ef
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 42c5ea617a25f019329ee172e4932485518dabd01983249189597473b4a6616cc5ba8ee693e0ad1d76e0f0c85ac8c0fb11ecb24cee2cb7358f7593b9fa8b904aec0573eb6d99af92a899d9d0fabe5cb349256eec9797422dd60d7fd5fe73f2cf5ead7fb72fd85e3f6fd284d2edfc5e77a03ec5f73c4c2f420728220fe9e9efc3
+S = 6836dff1bea541916b9ccce2695e921ff27a737ac54f4a5c3b2facee80a8dd3bbfe86c93a1af8da5c6b3a92c445dfac7e215fa9f3d67c9589dba858a223f326afeb8f5d0f92f28ac4e3671c22b5b4e0b4266f776aca928bb0309929f2c452b62d462675cef09388e5720cf0cb99351d44059790720db82ce014d7e795826833284bd4205c64e1330e30e09ff6220f62c013c117ace4f4286cd46e52694c4925aba12a5278e47de910dcdd820396febe5179bbc6ccecdac1883bd408530bde92e93c49db2c6fbb42e9705f29703763b21a8172489d2831889bb060505040940e60f7c5cb9f58327c3d3f7cf7e18ad60e877edb65222a699d4acdcb358fbc87e1e461468cfdc82a8cd7fb1f82e05378737f4aa741a63ddf6039b23e1aa19d94e7087915899685add8a8da8f64a93707be0b6354c8e9a8aefc7484bb45cd0beca493a4a0aef0b6aaae801866b905683c582bf39f9cc0768d880c6e4b331da86506b298c180cf95fa45e532483c55544371468088b4e378f37976c397e09f89081f0f0b6f4ba3be6929957f55f14a88f6beb456b70e6fbc6227e98c1e8a4a6f734c9080c13ed58bcfb3456cbbc217653835000f54956d839d4073571d8a42fa2294df1a747e88af53a16df1834203009cccd6d61304739872ab92be79a4462125ebc8bba909ca2b4d91b9e520d6c681c2f92070f156e31a6875122993e1d94fc3568
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 3ad62d183432746cfbdac6d9c87148bf13df52e906f67c573156fc407f8d2f576983754e69164298b20172741e02dd27683c2c889bdaebc2caf5df5602b7995f7dc14b1a18cbdba5078a3607c8d7e771550de8c49eb3b752365bade94dc98c0ede585786299a661b643fb99cae388d26441c2da2f7ca0b8fde500f02480b2fea
+S = 817ef0cbd8bbe2c93d49bbc09c5d5fdb0c36ad983f0e1f45b41026d3efabad67c69aeb07a0bcffd57c4c6ce95857ab1dd6e786f83d2bc7460366cf051019168bfc56edee99aca9b3862a77c8a9c22787b35004624a7baf963b6e1be2530b0ee43fe44bf21f52e23b2ea0dd7a9cbd77c960d9269bc9efe867f10bab0d27eee85fe95fa90ada2171e9c0acd17ccc6132983276d0c6f1260b8e20ab84ab4eaabb5db220ae7becb26f05e32df93d2a759a9d2d94fa6cfb2a54ef20ea8f486cf587eb2977fdf17e4b65bfd66497aab225254d53cba4b18c9b4c8e30e6f5010eae0d19d53b17c9ba8ba0afb5109dc45f7e39e604f57d1bdfe3a2354346f462036599815578c497a9829be3fd73b4d7fca27385cbe44faabefbc25fd599c3e817a606dc53544e6e10cf3182fdb806441d470f16168237685e2a384391c3b15663cfe9a00f938fb7f9362752e4377217c06c7419a2426bfbf76b503be486a2b90146e9c75718b208c8fc492f47d17e4e8f3ec9b1dd5a067cf1e4ced4617243217518653ee3f30ab3a2c3f95ad15e6939f88e169c643ed2056d594fba35c8e8fcda9f7a5fbf17ffc42ccefac0aeb95cada9b48fc4a9456626ec017b8dd995cab7720cdb7c093ffbd3b2c149cacd7a2328b6ec825376d19ff693a8c8beddb9cf2c67cc22bec90f1d4e0a310d7d7f81582b56fd2127fd7a9c1d3b8d1050ebbbf06be49da1f1
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d0609608648016503040203050004404f6c763ce96f5274b8ea00e1e795e0afcc8a1d1fec8879a033437d0c153b2ef5ed766002b39b50a10f9cc919f57cd0679b82940ad47bc8b5961061fe1575eaac
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 96c824575d1e537b1f8d27dda15040ab262f9416f0f61260032786362becbd41404fe9f8a9ad46b81f68fe16b3dd4b741396dbd209c078e744dfe8705bc012c90faf63bad1eb70938457dd7b83727d05e689ba04012c38a12edeb5aacd10342d88515a46dcbf1835d4c18ab318f81f872772fb54e12199b5488cb58b87c56996
+S = 336a1580b52f2b15e7fe7eefe6d4503fe0985bfcca17e5379d17d210be01e44394adce8d1c482db58ff71b6ba418b069fe15153ffac74b3f7190df14791f8532adf655721a5d113df77d164226b941cabc035853b795db3dbfe64a0a89fa8728071cec0bc1264cd9c7d43b429cbf868cd7e2ce9f5f71c6b1c9705ff2d99f99fffc6bd964e4aa85ae127e074a95e396551418acc46fd22d61711cc4dfd51428130b0036c54120723bccc8268d9f1739488e4874c7fd77a207a28b97f463fa0667adfddb34adeb6f11bbc1ea2e057120ccbae92c3504d14fa4d87768e435b1479237b61178e48232c6884c94f0f287cbd135ddb9629678d7097f8c966d1b74f288a8d307764cc34e3690be4e790c57627ff1e6ee2572afaef68dccaf441575dd5112341f91c0f20efc8a75047672c190403e8d5aeb1005e2040502d7cce97cc8977315aaef7fcc9c5b0029246839134dc72f72dc2e80e1d3d5e48881dd71f6b2accf21635252d82adedcf86f58dbfda3ea1c0624fcfbef191a89a43d5fbd62cf6142cb26c4cdf9cfc0d8c993b3e80d551ec56b29734ba77dcdb03cc20912ad85efc48d314c42b15120ecfcc03d85a43f2ae733fd2decde46e535aa84415bcc7de4203869ff945176b9e7047c5953bf241e3b537a93e62b412cd81591d658e7f55c4bce859bfc56683abea7e6e1f87f807ae05c52ab504f0341d301ad06429fd964
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = d44ccfb041a426cbcea27f0d5e2a77b21074beb5c175bfe5d39a833b2cbcd26b81519cb9d4df980e3bb72b4be4df8bdd56502492f9613baad984d132a730ca8d011e4e54f2b87060bdcf0d24d68cf74032a95354c0e0401238a4ba981310bdfcda1dad28a417f5e8db52ef413e1904052ce714a41fda1745776405157944f4df
+S = 5272ca5de6f01c255f59460bf1789ad5fef5cd25345d701c045c3623933f6d44389c5cb6eb3746b0aa75ad49cd5900223ff998d5752ca0c164dffa90cd4a3857de3f4c66e9d3c19bdebc842babc4b0fa60bdf53b76efd35de73230e283a590f4f4a9b7658ab1e1e0e5631534710ae18c7b866e79be08cbf3c30bbe6c0daec86237c439a7f63e57640263a75ed980f5180dea5874e2af8348bb15b833055936abdd01f8e5d913499382496691b6c60b5b2aae76b8c51794dbf9d9e852e62c410e9981b5663c59a0e5ba5c1545643de0fc9397150518d7e6122334246e277570ae2bdc4e84e916096000a44ec2e68943589d62b24f45594f35a2b7197ec665d45c3d9d403e7510f536a0e214cc6e3391c0494c5d52508e777b851157ff091995f4e0d2131f9e40fa4e81091e46cc40c0459a4f2d5c198222f0c7b39a5e2fe86a6f964a966d1e66ea550627d4b21c90cf3beeb8c4901a2ca47ed8b3581f37852f582382922ddf0fe0e322ef9409ae860b251699220efbd41f09968d2787d4b7a79ec4828b9ba1702b5da7751546ef626f2c7507ca4201e1845f39af9d813a45eff6ec0c234ff31eb9c8c2f78a0d70952ddf010ed03279390e13d6ea464171831ef86855816f9eb25c44e94ea5a40a6f134a55197415c7b621c7ae5cb29ed27e9bab16c1b6e7747e1462e64b99f5b8d07aed6c92ebdda2802269cfa3827d3e65c8ee
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440b6f769c5eb51469bed21e0e25d8eb3b9f5909a58eaee7435ba9dfcc3bddd272f82d00c6c7992f5caacb7814315f1f58aece9fda52a15a6a80a179c02bc194614efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 25e0b881e32da938611b4156525ce24216c168837fa84479ecb72207e9984adb6eb7393bb3d607b1469d9b7c3f4fdbbefaa4b0218850919a7d66a954b315129c39eb99f7dc08df5c4c8c90968f3ce37b66ee184ef3d485f83d308521aa2649d28c319eafa2aec87031a1ff5d7e933ca56a2410593425fb865981b7976fca021b9d7c3198312fcfea5d0093a62b4a7c49a985c005c3a7ad816e270b25c507fc36be1c4cc0a07cb7c6fa130240062793b18047189aa5e79b16fe80a6955191f5910b701bc1aee6dcd5cefd57194bf54d8e208ae41202744190d5ec8bcc2f977f11461a5cb4306fc9b73afff2863a7b580d454bb1fb8dccb1cbef27945109a8f5a3d2b1a32566aa4e8c01a62a1d735117ff5a6a3cc7e70756e7df10e97ee75c5f8ef89fb0a97d7a35698069f59a9f365d4396ab9a764c2fbefb840faf5f57737801b73ac6f9f524167b4f3a567aff999a0db10d55d82155720a5ddc63c35b6a632a3da59c16bd0c143c437661dcd339652ae42f54f8b2d8e52672613772abfe8cf0d6ebbbccc764b51b3eda2ae28d4ba8747a430ccc32c73baea63d050b86210c485ac9554606070764cd06b423efdda4059fc45ffd7193f7123d14014d5bbe5b542476e7bfdc4905731a0d9987fe4a68cf6077c3df63778af08a1f4eb8f00a4a8e03aa8726f43fa829d87c2d0a32e16b47a3f0472a6368ec50a144234c802e6919
+Msg = 1fa4b8433fa5d5d2228abd92b49e6147f7ed6c79a557102517e406b26557d026cf06429a5be840ecc0f0c9b38399357860c3ba23ebbd35b377a3273237eafee8a33997d01d7a0048d532820cea0ddf65d2bed89efb05f2b8b2117a5f4509c71c64e6bfcbcd839d5029f7f1863022e7781486cdd41d58d09c90d7061fd6ddb228
+S = a65d94748b11294edf430b91e649a7fcbce5d47ab1084c0dac64033e582360f7cc18c1b7e71f8cfa3c0677505fba6769af39bbadeddf6b3ea1031b103f3fd72f3c4d56ff6a75fc2e16c4eeee8a1d4be05e001fe210d07c1df1e62d17b9d9def6d981df183c97b4bfba226cf88dab793eef75fc99b028100ed522e98de4dd5c26fd954a928619ad6024ae454f11f1b56c0c7f04442bbdf4ca282bc76f7f054d5195a5ca398d06e8f149b0044d310b74eac7a14c2dd9999ea248f9a332b62ef97867a4e4e312305860a8797c5f9bb66ca4fe13c054e55948b1e54dfbad12015854fd4ee347bb19bc2b59930056a712f090fccd9b31c96b3426ddbb16c4cfe130b0f8327fd61e1df46e093f6232cddc3f9b43d8b5a7b8edab6937d869353cc3fbf8d050879b8fd8793912f06a603a1936476247ea140212530397e3ca5a593899198e9d3ca1eff1ba302a0713183c7e2d60a5492fcd8b1df4e787dee2d305153ea690d81b194205a54425c1e1df4364a20082868f09b5d11b5e5ebb77e41b5eb91d4ac73a75d29f7bfba2e056dc8d19a483c4256f68a3f4e80e2f8a801cc1401286dbe15636c653a80dcbc73f249fcbaf4b446e21e9cabca231615d44578e2f8466f22e9b2b03d21e2f4e19623d15361336763a28dd989bd5a912fba53bc4d5ea1c790ba81f5fa21ac1a0fb43fe5a550108a27041c7e854e7aef824a29ce7ffeb62
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+n = b10935650754c1a27e54f9ee525c77045d1a056baedc8c1ba05a3d66322c8e2e41689ca02b8e6ec55d3331cd714e161b35c774311540c6410cc3b130e65cec325377ccf18a5d77054afaa737e65b68662327627f5d1092df98c08b60a3ba67599b1406986f441528d2f1f5d6fe5ec6b8aa797dbdb3162876b08298237af81c7004863576af572ddd66c487cf32a82d0f9fe260f8f2681613208aec55723622f50d3cb3bd33b1226d5b5b9ea2c97a2c59054e31536849ec2f0f2597c077e621ddea0a22ddfb1df925c9f1941cd431afce0398d28e736cfeab3dd7f062a65a2a4c1ddca1f32afa03b4ddfd8b7ca40cc0ce2ed42229d753f03cc6d8bcdca76ab7c2703c5ddad08aa9bf9a27740a8b23168c6b55917bd3d5c1c057c34d1efb1411da51ab745519bd92b9432fea8fadcb9a70e5dc3adcd3081d3333507b7b998886e988296628dd7265e64eab557712556cc492377f15a078dcb620a6e7f051a1fb8754efdca3de253dd0aad4205b032659e4a4fb307f074fbde340702b5911acb34737d7834600cf2ac77f62f83ccc9ba78ff911021b9f8ad1bf421430ae0d64916944b504542c0f6263c48e5e233ef1869df1efc2ccf6f4a95e4db2de7b4cb1a992bef6573511bab4bf2cd58e72a0c235f56dfc182df4dfffb69433a5677415f35d84f5125f5200eb57868cce6b74c5833417990e318372c9239a36dca1a0b28809
+
+p = bd4e8bb7fd7ef1e39d71de06b0001bdadcc81b0edf2226e0d056b7eea70b2249000279cc1c04b1ac2919014fc3fb8b62baca3e261601fb0a58a9f67f03cd60085b2d43906d36ad014f321012a9bde9617478a0c10201afd53f2207de3648afd1d737afadf7fd2c0b9824d4f66b2c7dfe93390888ac088c680c27b1b2486659ccfa8986c8c23f78f18b5815a410328e629e7440221bffd8ec4722bba3420da5234f898f8cd7e6d7dcb1349bc4a0b665b41d930e3957cfdc88797aee5b2b27dafb5ba0949e3dd892f490212dfd249f4b1d99fd3b72695ee0652997127f0b9b417fa8365ba9fd103b978309d9baa9d401902cc107cb8d2af7ce04660900e3707ab3
+
+q = ef67f69838735c055145d21fccb42298642177fe3fadc39070a95e4fc04ff058aeaf9070b4eb2de1cca72d8533bc55206d2ce9f2895b148da67c89e5b6496ba682f76bcaef69306a7fa4fbd41a838bdf0fab3e7b56c27a8c18dc4bf970364dff7427cdcc6f532b49712282370a718b7d5287bfc02c4abc35ccb2eab3777f5e0d8a27ff9ebe13e725aa0a0cd48aee1fa33ea6b4ea965ba42fcce7af3c528a6675cedf4969640f2ca73345dfd322620df9dcf16520195df8232061e2bc89c12de24838f255e7b1c17713ba435d5a351e263350198b3fb881b8ce0acb5aa58b7afaff184489d167c9af21e40e2ba9fa69b44a3854329385c97df0de24dc283a4053
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = d65a050fc06c9f176a6be7a7bcb0a9f074112ea5c7fb03b04bc2fb25143477741d74e5e2ea06873a6c2676bf255ee6668d57ab42b3f0fd40278d781418b16673bad04183ea5e7490152c620056f4a989de33a8a199363f360f78d5a0882ba0d4731520da089ded812d26b351969b7bc1314b2caac1f851fcc82a1cb0abc9abfd
+S = 77e7756da33c3918b94a1faae80f2081606e9646ccf2be6aa16f2b4fbfdb8ba57fdcf61e892cf9b77d60df62c07e56fa34177df466710c7f3b4c5084647bc9c9a52d66d080b3a1d6fac9d439cb6f207a72f70337ca9c357e16278f6f846f7028345dc0ea8139359ad62a103c43a922293afd300436d76daa5a92f940df6f21f1c442ee3d4aa8488defebf29127e11413cddf4471fc5324ac14ffc97403505867105ccaee26c742082472f6dee0d985f05777d6faacb166f34da96057be40530df9b1076b645272d154614fad693d4d5270670a20b71103c0e740114f3585c2ae02a4865e0277a76eb173bc2ad65db5e0a9aabc5d47f903643a1cff148703991ddc4e05ba766712a93d3243bcd714d067c8fb54eea3c3b5e69cef976c8794471b5afbcf7e327f14258410394d388ce095e5a623a406d33238d2c37a29eb1d099a2730185da1b2e295a55f74b555a6d6beec7fa7b9b76d916e9f487547d06356ed9e3ba818e31825e97b465174a7fb8404b7da84020f555247c2f03a407ce5afe07d3d9df9c94147697d0591ed2ff6776ee778cd74c07e071bd8b2260cab2e0eabb4c97af8d5ebdbac9323b0a73a9d93d27a635d8d5af1651de596afd4c9012f9f8840d05e80a2afe47399cefebb70450fc4b501fd69f67867123e95a6ba653f69cfe3cb5a38e3ffd92d2a37fda91c06e59eef42c836b50050f8b9fa808a4a114b
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 7228696b438ee71ee4be5fe548af7423508c3de7e370f6cd416ff61f94d5e140c9b21f4b9d968df7fb9972be859eb43e71d94cdf968ff7b6c61d2ea95f3c59d41d83402c322ec262991dc90ba7207dfde371b8fc1782ba96a7f91f4b22f90ef117a4b2572adeee2966534c13d5bb37294e5d6b878fd1a9348c0baf4d0695675f
+S = 34d3fb114d6871eeb6a9cc9960d655df44d2a5c8f1d8bbf1b3b03896f5ba8178c2e92f8c420d537bf9f8e23866c11d0e02e67431a1506b35f97a85ef220635a28eaa76659fc8fe07d0d4f06fc43c2c4ff96f8e27965078c67abcab78faa4299d345ed81a442698ca99d1c0e4f0baed8095dce5d30add437c1f06f79c215cab5ff88eb280de1b75c3f19f8a9c8810143be9e127b04fc0316d65e7cb4af7786886663062d88ffcd0e64c5e359874db6bb63f91e92c14a4f3893d6beb209d4e009d646d14d01dd3a84f445ad2f54877e0b529356d561665e7be8332c33dbce60d0b2075cd88af0bdc6a0d8edc2efdfdacdc5bdb4bd3537f28ee523c1a355cbf94c04329fef5c75726c047caa8119ccc4e9d60f203b0fa48400e07e9270758b99b0fafa65c0cbaf40cd3408716e257c539cb6aee3e171830e70db3a5110ef5a2561f87bf9b56ca69a61f7abb1b0be64d2627d7d78055f4ecec34c9f9768cf2c21f5ce656d069799476ba6c2b223a17dfaa6e958b046658e545ec4a28e2b6565bc320296ea2a8360b6f980d8e81567a7c40a32c82e2576ebe9e2ca68c46239e2638737075c3a0c0dc68795331700cdf2ed1c81b44b69afbbc7776e08ba794be48f16dbbd8d21505d8749deaa470aca86c27314675553afe88a96b80a67e4257c95a57bb3e9262977588717b54814250cce8bcf8e260ec58c6866903bb3f635148bfa9
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414e3a0e0ee761eba5ffabbc08ba0f2fd689e143a3a
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 92e658a7f7bef5990043c260671864572e070d373345af8304f76923f4f4464e6fcd26ae8a0bfcbfdeb73a7997208a2ec8d8bfb502000bc824c572ab742b7e0eef0a3535de554856aaa28d43f1e7af48d9822557a57d6062860f4909b366ea75bba36b841a2741260b0da2079ef73c6e0a0e26654444171ad1ddd685d82df14b
+S = 4496155562e965348a09e9a67ab0009c2b74275a209729eba350db82e066527d9294cea63a56ba53718250b86c64d29b327cae24be1d1b6e3eb996e539e213af4739a5fb52970e89d6ffb0e4f7074603ae6bc2afe88379fe8685fed5c2e30183199702b2028ce39192b35ce3a7111573b148ccc6b7bb15c6aacc4a72819b860f3704a0660241a5339ce3ac7eabb8eba25370d690a0c478b3be35f3613e6be74fd9904d32bc51762d9c921276159e4bb5930aee4ac654b51c5c77b84af7f71c4b88714b1c1bf23ba28d3ddf32906a1497bcd86fe2d8a6f369d145439119028c82d0cc2eab42a4775193d7c3db38c1b86c4a4c697d726e924120852dd747da3bbc77a906f367cc5f9303b6a4cd076bfd4237975ec9cef8ed1d637f25ac0ee20d1bfd918db031102913f8258de26d3319268d97983d29899b8a394db559a95f0fa46ec4fdd77ca0d901aebf952c321bf38c2e6e7943af071a7492b5220e4ee1a376c9c254cd958a743d47b458a93d993b3f011d81afcb5421ffd4305bf6385084ab3fd2159aaa76510a0bc20abf5bcb36beabf9e1dce3472961998e6aad1a68935283e62d49334fd1a3e56cac2681a9a172686022e1ccb5a215333da9dff877ee2b38484e4824f28eaab90d2f10973cb67f0b0ff7b32733464d1553f18306eda6cb50155a4047e0e39dff11524f97819f73bc3482df0e7d65bcbcbd4dd23f845dd0
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = d51a8b58c08bd2f5d5cdcb0dc596e5a2999e86d6ffa6fc09e5b9b64246b2b4d044fe3c3178a3cf3286815b58f4d8b27f3c0b3bc11fa4e7993d976748e3cb9d7824d650202b0923a7cfacc84c688a71c5e1b187260f739f0541b0aadc19586bae9a2b2fee81c3b89cd9d57ab1cab40abdb216d3cf771b0b951b8be5c4905f08ba
+S = 068f422fa9bb79c8f18de3cc684be48ed59521ad0ea3a36326f0e4f96db1f2380b4e6a8d67f15a13b68ab0aee7a7b4d0166d94ccc1ac522de51052ee303c56ffad6d72912443ac8433c4e10229d9b9b605977bcf9ef69e33006c50e6077f6f0ac5d56cb9ef36c3de96653748a9d720841c9e4993fdde385ef8d5197b8da2c9c9b029e58d5d28c8a4d017556f31d45ec3dafd5f92a99c5342f31207b7ca9574ed043279f0cf6b5ecb4927425e149609009b5fd0295faa4a189d093f9635de49c8caf34200ccaace04c42c2f57136618932556a20ed057d60dfd87c8343d3a1a3b8d7b760453877ec67a535676c97ea65fc5623b9b7eeb5419840a27d872b199686381093aef3e968af7c4faee2e88fe7904212e6733c6571102cddb6d222e51aa19eaa59afb7799b0590fa6114c0d0ad5a4b09b104c3b0d1f31c8e90d8abf26516b72c7d0b1533bc66ce4d0e25d08454fa766522a4278080a42eb51d064101c1d845361d4ba69809d1340ab354f907986f759ca18d62861370fc4a5fe147aa6504387f1a5285629e3fc92b53abaf66d9bc135818748f59902752359f074f831a87fe7fee433a8b564e61b07500bc0610f8f17a172f92117edaa9b9e6f5858326590328cc9f12ef630f14b1459f3e6db8f665cc9be64285ad681f5728bf1b1507a72769f1db7ac1231d123b6cbe57f647adf4956b5237e7f754ff910278de89a7c
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = ce5ccd9b81d0103e99c4bdd8216b4cd75f4063174ea2eda94fc16cd31bbe9057fc0e08f83d20983bde3f6c6b8db9acdfd24150808a92368596557181d445e5a04e91112db2812b58035d72378d8bc00a1ef75ec373b81dc6f1f0a2ed96f302cf2eac8f42ca3df11e6ee678440a28b0dfab2a36eaf35bcbf3c759a71e47120f6c
+S = adb58e2ca61b110bcc5697d845e3f035fa8ee93203f12475ae3a81ca0a9820d799724b3323aeee7d3d6e978f324c84738d6b56c37dbd15b71bdac3a4102576886978db6d78a0c0291886e3eea01f1e95565789d3998a2613557202cb598d560c1e158e3c30d89a4add63fbebd361a17f332c5c69857b648813cd90c2ba48b720601e9b0533c6baa740223dbd8682fe0ddce8a6d9bac06931ce4d0516ca1cfd9cb06cad6fdfc1faededca19480c247a39c5e4815e79dfcabe5f4fbb0ed9ba17b4f7e25f1c55ed71c31a5e559c60158bd66ba199bba3e091e20393377b3a4561b9f07aaed7c0dd77d41984cf47bf34359b3a513618c4595be045750d47788b22cdf102d7d10726605706b772d2e773215f52b9c073855018022848ad75d7483aea8a34af5a900025f71f0b46c587a550dcbfa011902bdc870d6cea895640e4c775c954e11a3423fc9e0d6ea4421408816ca066586a37210c7ac8aedf032413bdadb41c0e6ff5c57d4a77f71067274d43ad9960b895734aae6a1176ded2883303e24100398a4cca23dae13d018391a8756adaaba709354b799f22f27d4a5517967acbf694e066056c49da87df46829c1e4062c535c17b72989d7eb045903665576e6144478e8938b0b2fb4a916f9f2f65990b683c49adeb6e6d6ab7a7c29c530217626d1429025b7cf627f72c4c588ae86ac1a1aec4120bd4108943675e53bb837e
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffff003021300906052b0e03021a05000414970d2e4e51ca9f81fe2e46fe8ee73b728122b0eaefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = d8807c9c2e144010d462ddeb70445182165168be1a5f33c22346b6cd81e7e162c16dc2a77ed3f80c7aa76b2ced0d3af81c06f5122ef20d773b548861a7d6f96cae8db0f73f7d2ecd0e60dc05e5a3fc263ab2df8f07755816d61a72f01b165ed1c766af531a1bca9cb915973b000f7d5499dc8efd4eeffee71b21da4188aff6d9
+S = 9e7c462e899885020d173f427cd4e15994749339dce4f39a1916635010d984b6d627da831d4264ae8f929eb66b8b14938ae12ea74e4a51877facfd402d0b6945a299ac6b63ac800dee3c2d5e64c4feea4ded7b3523f4fbd950e8647c32fe9b2eab6c64d74fc90d8318d52e482e811f74c1990b80d07622a35d7ee430c5beca1997f942117e48146413a3d07cb42ab16657176edfea16f5ac4cef9870689ac51edda514099ed6665b289e0ad9071b35c9ebcf06b0517260e47a516ff852f278fdd7b3f54db18bc5491a44dc87dcdb92a3e9282f7de19db80424703af856a361a9c9f685c3b16efb5474cbe23c8f04e3d5c5fdd0ae9dc5d73f9f04e267bb4aff348c55e2139fe554dabdf99e90b0ad20a01c1e02af92fee0d8a22136f8953bf999500a6d1a5478c9c6ecfe123b068085928354efadd5a9e41e66a15d73dd5966eead4d39491ee2d74bb6ee5608089ece479e53d599f9c19392ca064761688317d0d178a627b7a9059093107f727f754fd538e223cc6f01ad991c4c35164394f4a60da9de6b1b2dcedd892eafe4e3b04b99ea2f6459a2dda8eb7ac7020bb12656207470362c0a10ea79cf3d5512353aa87cefadd601f25ae15068049d2dc158c04a3a8e00ee4b8af3a430890b572c414b28abf2aa14c5403a1fd918baacc4f6b4f80446dec87ef2c808697f0fdb8f142876d8b7d8d90536e3119bba38fb4e1672ec
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = aefe857b2bd74d6bbc3d1376cac4aa6df362be9d5d77c5f54a0c336bed58ed9b7d8901b187c1948a885e1c16bb7ecf0130c25a921e53d7d37a23f9f2c8768ae732a01857d710ebb8658d3ab7eac09ed6e7f3c65aa7186d64ce0d895e351ec598f5cc3233c2cc393f7b53d520fe91ff36417b69bd9fce6ef16f514976db5a86f8
+S = 30de099e81b7207862eaee842f7bbca8db96c4348cfc148da9ab9bd6479ca79f09d9cfbeab93c20f58351d18f7b88cba4c1ddafb46ae5331b75d216cbf6fac92cca17f2cf7142cd42007be50a24a1c53ddd69890673ebcf6d476854fd0a5f76e7c53b40890855ac801ff2088e0d427ad02d8e43d499a06670ab6e8b43f661c16295f7c6b04ac5494ccf27bc49b5c65233af02d6c15cbcccf40aca45929fc413c566bd07616748b9e5cc8562879c2782c1345973f7777f56ad0dc290458b6f3b5a88f160a8eaf8ad0fc394b283c1acdf9bcf2eccf88164f1b868d07a05b7239e4858c2f3d076a299a1ce032ee4967f7da07198d3ca26912e9ad2db79ea8f49f21544e82f6e231651805e934524899ef854255998c1cc59de1ae49e482ac801e3c678626b3b79bb6be296af03c863f89c73a87bed864636eed84c0a5ff05cdec57a3ec76071137fdb3cdde2c4f03c3bbcffeef28f298dd13fe669396e8fcc3a478f4f3793693e8183d96425ebb92f41ae373aeed30182f8a6bbe6b3440ab2a22ad0199bc59fd631e221223abd2358ee6b8e879b2aac64fb41257fc5983ac3e2de5386819042832a8bf53313c0d77767d53a148bddc46638acfd626b908b056c71292c0f9d1b1ced4f2d2ae70e70de9b3dfe6b150314225f21c03b8b53baac3432a72767c09f360393feb18854ea884e8326b94c225d871cbb003bb94d91a74b358
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 4793168aa3ac854a7e0bd652b8a57666d96ddc389aca257da748fc46a38ebd8e6c90da0fa1057d5b621c6f27576a38eaf42788a7fb9bd50642d346aab698d0bfa0a29fd22708b7e616fbdbc4e0b4ad92e2ab18a7e70aeb9ef161c6a9379b3a286a312c7b3c9d7a142312e2d05a6a1f872a6054e267ffae6c3d5a45ec2d7e44f3
+S = 9d2457bf29a45871f04f476eb7a43238d3ddfc7c61fc2ad160335cd1c42ae0da5eeb2ee10f2528ba1e645d27b306f9e833b86ab62b1c4785d9249be1ea9e83e80a5b3a774f2af61d6b536d7670833bca21406cf5dbdcbd2a9e17b2679dd33b026351943e841a7ba4fa3f18e2e278a9db180757021fad06befdbe75f6c77a36518a2c3b88b6329849fbb1007c7ddb7e278b64e319f93b4713717282e5845a168b7825b47f23223793a7a93adf68d5b83c6ed2b6cfd850a8c81589032047fdac6fe091e0369a07919329845612a797dc7f9adfab30255e672d8fa8639a597e556b215e83115fe2268f1c9870b1ba0caee15a26c45acac368baff4018eea4414eddd86678e30d2a46ed879ed6795641af64cdae0f94686c134e1f05dd4f59936e1450a26f2927de6c44247bdfceba2b14cbafcded775da0fb0b81baeeb35e52fbd44d7a4668fb4c832ac0a9c622dce6889a1df6d15ab6c956dc4249127eb7f1b45379e56ca7caaf89617491f5ff38daaa5f0d58bf8eb0138919e3e9bbfce08861b92df0124647bc175bb000d8d0661c71d27294dbdf1112d1461081a931c036d5b2e204e94bb3a31502d055cd74869fe7ef5ef78657a194b9b4900f8882c25668d5e1abf37b038a716a2735bbfbed06b2b55b514f24dbae2e570b9b6164707fd4307b7730a48d3395f372be552402c7c1afb94516294c7823e4e295cff2f2e866ed
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00302d300d06096086480165030402040500041cd79527d7b3e43885192c0577d81561869ffcca8d1a7ebf268ef448d2efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 8a64b6cc5b6a7947d76c4f7392be0e56cab7831b4a04710a8e42d7b828cd727b63d2832125acd2e21a6df3920ebac81c9bdd472b05157d2a6230d36ffe5c91b3fd3ba0c6423594809012eafbefc88dff52919fbe764177c20dd7e6231c52bffda2c696217aaec70b8284bb15fd8f66ea36fd143c673166bad85e973c4b550441
+S = 9d579f90d7339f303ac17951057363d529d1b448daa7d7025d93b111aeaa5a1087a7063515b01f30d245a6d27dc2074a51f33273405f6db2ffc466d96b822b1224f07aa8075b9abf044ad120eeb39b2e48d5f4c9f7aa1657ccc639873eae8b9218f3e800eb560d5a04e2797fb8ff3f7c320f7122eaf227febf6ae3a8e2042074b7d22222be95ede069af032315fc264ea1a85af5de920f1ee1ee3696850b581f2eb4c342d5df7aff1ad5b8164f9ec08f77e60c0afc256de6ef1a18e1e113a60e7b5ba8a0c665c0cbedb4a56a146a1662c8ec88d5796e9352c36f73a5f5845659a0711c818b0b4f7a20abc52a31474f8a51678aea7a13cd3d361ebdc758fbf90af9764bd757c7505b834105f0ba803f444f4e17310fbd76d4ae2205ab134a6134819ab329e1a58a7382624ddc2bb3f54ef41b6549cfd1158a3c363e4c0a5b3474dc75baeb43baf99df031210be3a9ec4c4e910768715b4763b4f3ccf60af91984e17495f4064cdeb4d7b280c8c5565a6c774960bf2c71a917b955f258eaca5b0bb9f48de529b258828c138d606b4531b7f621b9b9c1753db014e8202e94e8ad10c18925ae170ec08d0a38fd493f022a618bbadffabe015ee21414d893cdf20226330b94970d2d9ce45bf63a664febba1cbc3d6fc20ef8f2283265d1fad429bc4c0c010022113fc81bafe06afbd7b6af26f369fe526936d233f5616dc5ddc7eaa1
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 9186fc389b58e4aa051fc5a96912c940f4c0159780a5062300fcba1a1fd5d32a2467776a19a79b912c1a826655e780773930040e4fa2d661414b9c0995aca3b58c10dc204a1c254038a6cac1a7cb4cb1b63b617d75d83b1c4a800d8a9426cc788f28334278dc0921f16ca6a2a6e5b456318a33cb3b6ebfbce4421685656bd5d9
+S = 2e7a8b6a247395fc2c4aa4f0fbb4073fc25923bd456da34955a1fbdc66049fa20d093818d0f65611dee0ce14d15cabf313096d629866bc3b12ac8805b9c0487c92cd5500bb5f1258c8769bcb0bb0ac0024d611f317896c472cb9fbe100a40ee6910331e77120bdb6d31603774a49ec63fa0d5a66bcc1d21caacc647e4942efaf53f28bf4c8685b536615ce951ef1f9b790fb1e5e423aa581b54d3ea30b8cebd8bd939f17d0bcf551bf36d3d0080d808291cd60240aa8a6ce963c5688da23fbb992d45a4075feb1263310cea1148ff2ef382b2fc2f96eef811b338be205a0791adb7c07895dec70d75ea4f6a3d94b7a9b072be6b5d72f964e74decce749f3d7ec84e929a1db42e7451e50d50a79631a44ae1dc38eb4e541640b421ac93d33917680888288e063011d80fbce554bec874b0a4d4670210a9fb9f73858e1c0ac7c98d01b1065f2e8dfae52ece1a4d3fdd46d48b1dd0d77bff7fbdf899672c9306cffb4c070f83551002dc564307730448b34258e7ab7a0db18250950752636e34484b7e9063479b2266e639a4a6d3bcb3c9471f1e466c5339e10007751e7392b8591194ab85e00760debf22dcaf83774d1ebf59af46859c264bba1387b6cee391b131b9f633bded7f1dddf7a370742f40a3ed1ef7f5a312e5e26077109ea298c8932d4abd003bc407cab7612db67a94840a381ea7cd084e4d1825eca83ab84ea7043
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 9c8697689a09da7917bd79af7bc026c32837849ff5f03a1ede464513fa45928cad0fcc581e7e73c6eb0b2eb01cef62b8568803d251fdaa038c25e86840a5db799259fe8f0cf645a44eed6a5a0192813f0d7dd3500c30e9bcfefbe7ea3e1d1cbcb52cd6164db77b9aa829d5b613f0aee1b5df9d210cd11fd19b90e9a1dcf57dde
+S = 5cccfe2cb4098226ce3988f1fdde318bd67a4488d48c8dd57b678d4808f0627010ccda741f0420ff14324c67489fe4b55356b5fa14219a6484331cb32df6c649e449d077d35276e2508dff31a421357befdcd05049fe9f3a19fc2b65f7b336e89e953414c708533bdd4c256f6541c87be7c32c2d6a34da805c63ba836dc3ae5ff01f4669185cdb2a57054f2d5645b4010075567374fa60d06dcee10595d35c961e350604d7423e5beb754ae5f34d3c144526ae2cb9583eca938da7c7b26765d5d2816a30bc390be5f1325f2eb9a934cbf9311911127b91aae4aa4c418192954bd89ebef8c54d575248e3827a38ef50486d0fc2ce1080c0d8d750c1bb3dacda49cbb95706fd4af5a915418131f429f50b55de551ec23516200bd5cfc31410d74e1ca7bbf79180f3de84ffa56de13e7f6651928065abd8d3bac5d18ae6e3e3801f102ebc7d08c20f9e9f591351e03c9ca3f6d12ef6bbe356916467154c30306e0519b853b4d073f10f0808a7e2dc22e55d4894c100ee5ca7209e4eeab9a346defe83d0ac34699c4776e1c63ad4807746cd1c05f4fd0f32c2183145eee8ad6df8c16aa00c33ccb871cbe373ff04bfb064bfdf30b8b096123e2e137952194765dbde4d12fb846e9baad76f1eb00ac0ec2c44945095eba3aa812a3d33b96d1a966829cf4ba7a98e8c794abeb2152237e8a261f014a19c2b110d1c6444f8fd8d69d733
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 4eab894093e01b38e38a8fc8b4d6ada3bc337ad1b30615035a9fdf24bc6cde30b46d6449afe8eb08b35e4411a1bdf1eab7d7cf0d5813f83b1063e714d376dde5852e84c1c054d2d3d18b31f20382dd76216e8d4a36b8554397f2cbb023106933cad532cf4c8b984143f79e94648c3af002dffdb3d35bf5c2f736d32236a349c2
+S = 96d24cb0170440b5a493d313a500c9d095952899b669494cc182f0616d0da2918f4644961a6480e127459f63551bfff6e72f3ba3cc5bd8f529c8bf9e2bb90c9c12e2e70448e4ee1923ae1e3561fb6b5bbefccdd9634903bea982d9be5521914e8d70a51606cfc1ab9806f68487998ddf94e00af91f64b7dc739a62d98dfca35ddf4ef4f2c318b3b5dbb58d0b892fe0932d48d4d8ce0f88eeffc9dc5b8f4ddd9f493a3b03c62679bf261ba8a3e9c98e478e9cc74296714a0e8d16f0246a1e77c48c6ecc43b4c0aaff9a04e6594ce508d4185ac5e189d2c0a124cde1d65e832981dc49a699f9c6f978f0949078be9fcc545d33568b632bee58999fe83a2670d24c03b8f306385674fe3120be26e12325abb051514c95a60b3369d04ad92b85423d7da9a06bfde71265fcf8c9fed0b320909a1f4c66f4b5b6259a4938983c8f547fdfb630a64779a5c835d82c5435f60ef8887ca47fca7767a27c267c9d1efc09018e86340f4ba3961ddcefdd2bab540fd9c038d16ec723b31da7b54f0138cb54aa979d726c96ed2de5b4cd238cbc54ea0440217c87667eeced158009580a66e7432062c5cc108648cd6e52e2aef481891cf7963efffd5f2c5d9d468ea32748b9295bd6d64ecd8744b4a5d44baa2346b2e23a88639b3e6de22d58b201b896bc58c916d748563d0f68d90819cd749f9218f715a012d0e7388dae82363815e389033e
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c25980db8b2660bb031224d824ac443d7f673a16ff6f4ca64774cd52c
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = b49b676c4b56eeedca153f915c23079f3e9b87a7d02b4565ec1702e77681edf234e716a3e0ed25527c5d4cbbe66c7a60ac3fd22921ad5b4eb147f97671959c21faa3b74378bcf431fe7626c11def7eadb455033909ac3c1619cb2f852da890c0aed632953a4cc154f768b3eb28347c50fee7011fb0af5085cead8e5cd2413097
+S = 410a01190f07def9bbe6b2834634d4f84c4f626e9e286d504c9393dcc751b76327443ab10e9e9da673e668831c231050b8c37c6fd0a92b814924ee73f0b6a2838c7c6bb39f02918ce05a701f92e38680e8c43c75a57ec2fc818316e0e32b85a5126b2ffaf9340338121379a57ea00b1529ca11cd5b6f444654ebf079bc44e3bb487943580f768b2a2ef9a31b0cca4c0c811124e1492b32f4c2a393bd67335a310ec1cb4cf908613c552a9dc68a99f2e633475e5f24c9140a813ca1539f63c7e241b700f202edbeb1133a043d61e93baef9f3a4c0f8e6cd14f9c2a8aaede1486e0f8da8c19b5a2147357f6059da419078e631e48f6a9cf888d22aaaa22073a896bff816ac5dc940b2383397f76255ae9559ec0812444d47f5b3205595c9db1a74b7dd40c704fdfdbe786713a3b79dc52b0c882bbb8a62aa01d8569966ebc00ea4fe5df212ee4a875afc85f48464cacd874b7a63f705cba529b43a14c483032d616f7b965f9784ec1fda02b05a5d310b11b4df17ec35c828b129218d4158dcc58753f5e208ad8a97e32451da1fd591101ad2f93fcd1e6f5d6fb7b468da1937fab4ccc8e9f3e95a4160b2055e8634bbd0798bf0fdeb658a435a21028fa7cd4be555767573e09d5053941aa0814ab314c45bb94a36997e576a026d017ec7a519237d82297f15c1906fc5866c1a3f6096ddb33576fc68e39c6bcd8f087355a12fd94d
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffff003031300d0609608648016503040201050004203a75e4efbd95ceba73b7671c870d5cd4613bae5fdfabf22e8b5b18fab56f620fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = b31156951f5d041c1a01991b23102d5bb4acad22c777804d994a6a9fae2ab15915777f0bed6788a928b3ece18f905fac06e1872412aba59598c978d6e8e15fdaf996bd82f6ffa1b5fa58a7b319f819a69f835a7b9c6185efa06f51edc3f43817e8d6d8a3430e996819599038c730a37106fbeecf6d82668438a4bc8b474b8539
+S = 9bd1789015404f8537c89ccb750e04b5fdf82b0daa5d56f40ae64459aa23931ee5d8812cfd01102e3749024a881d3e7a13269b8ce17cbe725cab71c53e218d4b97d4f1274247b112a4376fef4686ff0ddede255e8b085d763eedb7f17eddfded5bbfb0121a3f4b6d47f1bcef7aa871817fcffde3f7ebd75c00c5ab1f6d5b2a6f5a4ecf92a9aecf902711572123eac011bf9a406bf4da6ee6411fef5b82aea8038396052e3801381061e5ac04b8f1d0ddfb678f28920fb5ac471a7046383204d5add6bbe78b9a7c9ab1b3f9b4b5984bfc8a03794075cb101bba0aa2fc170cf6da9401850ddd86357b962582f9bf0e174ed42ce101692008e2ecb51fc1185be19017a43e6bb08e2df7082cc9221895f159eefefaff9d8f3290c9f76934d34882c97989d4afd6a42f3815f7d474a7d020c797c13a9b4786d68ca8a700fe3e0abd1df9563344f0a7bba30d043fc5fc1d3d585f54efaa45cddba963383a0a1f979d48e8ae4fd633ec6698ea4f1e14c6fa2a7f6024524e6db1b0b66160398919c4faccd105d82c54fc98335b531baa9a7c96582ae05be7d93b0fa3e92fcb7a2f30950e3f31fa21270882d7a0e75cafc87fbb387bff937d45be79e95d973684a9f2b486f6649436ceb8deda18aac63c0103c705361ac5b318647aa632d98edf09c3ebba86afcc00f3ebd27505b926a59f67dc8b436d75c5a449e13808aef13e805c35dc
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = bafd723d8ef5602cd03f8cc4f54c398a7a6ff4277a2cc9c77fb2b6bf98a66072ab2205750dfeb2f1504eb6495c2b56fdc1b7c2cf4c5b4824d953c8ac676d6845720d881d7d75f917ee4369711e3b22a3b147f58a23bc70c5a4df586026a853afb4c6e47d05e29c6751288f8263040644f02973a127d8aa74895f4d21fbe08878
+S = 4b5029ded3d15dcb29534fc7f46330bf5fb64ebbb4602874e26364aa52614fd05218973224b1936af01aae5990bccbd92c2a6d20d170acdf782020b2a4ee8ccf5fb9402838cf0017af1bb0e2b5cd69c08b2f4ef222f1340972d21e3218fdde4ba3af10c3baf88883698897c52c7b34d84659468400d4d403355d59f1e21812d8304510dd8bb2963c47d91099dc36d7f0e19f69cba4a83b40f49e332d543c7489c62fb3513dba94e9e98fbcdb2e8d71ff544b774b9303b5e8ab1102e4bb34cd6a4839fc007a5031d87b778e858f20127bb09ce92b96c149915a87a2829532c3608d77425ce38f2697df9fa992baa90900e85bf6eb7100ccb6667e093b376b45230c6ab901de3541fc5dafd0cfd9abaabf7d88908261d36f1146757189f51d167a7294abe9be9a16028718ca3dbbab7e5d43ecb428c2956cf1d44c3e8a875e0b9e3c978fb489988b72f04a9cbd06488162d27498b52298b7efa3aee0937cb0a03740d82d43e9b108b0fd5e80ea34336fc5f711c8d62f74011b893d41742449ba91fce88522cc76208bf901fbcaf84e9662ab9ef109b63d03a45b7e1d4075b2ba5323417f675f61c915dfaed6810f663bffcae467bc6bd7772103a0a1e445f2dab341025ba4c2bfc93ece19c64dde97ab7be7c00f9064bdf2a1fe7c4af045a2362d371dc30e26b8e25bfb258c4b479e5109baa194dfa4382669b0734f1b6ab63c7e
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 65d1c1c5f2aede8f6ef03b53d0ffac64ae6b9666b18a000e4763ec2997cae7e0bacddf3a284f35e270f3132b2d3c005135f2b10213c7221cb83ae6b96dbcbc690c1162be70faae0e2a11da7475f420186da586b07b31fc471490a43da3cd7190c367f359b2f6719a0211393692703441bd4ebd7ad111b316c32dcdc021462edd
+S = 7dcd0def685ce0d0dc10cf783ff7e71f69c18d7edf9e32dd583d46201d961cdc1f8381b5dea980ef331ccf27b2db4f7bca619b29c92e04284b14c6c2ed9bb62c323ad22130641834a4fd703dfb714d8d17939b34b9bda15a018b24bb596de618208c65feb7c262b8dbd4f6b10fac674855b5bd1fc15fd1faee28e39bc495867df3847af4c2b8b40bf3e5694c84ec4fca9deec321ae730ef0b10329318e34331e21ae5bc21bffb025821881d54d9a3f7adbb96fab78f1aa6392fa4fd8db78bd3e2bfdef787054c9c85cc2e07fdff85c48341d587b7ff55f9c96e32ef06aef9df62d5f9ab837f3538d822f862120d2e4cf6abb43c620a7cf08a8a72d3d9dc0f7d02d4c6fe620d3d43891696d7ee9731fe448a12070f573043378f3a2acb470fa7eaf01873af3deaa0906f28fbba9fd4b5b05dd806711427a36fbf9d82f627f1620f9d48fc10c2d1f32c88826faa6f49ea6918daab391079c37a76ff76a6a8696567b319c3adbdd0ee5c2dff7ea8411c52f719ece66297797d3ccc99de851f14cd061dfee6288766149dbf4df8ef4554848f22e3d461f3b9eda7d7cfbd2e5b60b434d86507ad1e7718064b030d470307c22ff18439b2ed3e1f757eede270f4ef8b6e75ce824d0e65f02631ec87782e7b4b39bcbb152230c93087676707206fd4966a4d7953931ce284eb7ff9d5b9bb7a86ad7dd561d334b0052a6a23b25ae9a05dd
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 01fdd22335a45577e5cc758f73df444818c364cb28096c6197678e88bd687746566277bdcda9e200ba02b625a95a7d9b1db875bed471efa94d9bf54b88c32fbe0de308d32f8e0cf2926e9421ebf0a662073e17420f6ef2af0af81e0aa36e3a7d2c67cc8fe4bd9bf575f859abc1098544de3c907f5f683f1ad66850eb97cf602c
+S = 2369b3beff47a12b51b8ca1d8fca20136ba94bfc7c16ebe84d322bd65d569af515521c1ab131ea2afeb2620c823b1753a28d0207c7b9e97eacb303a62da587a7a0417b75b8979f492dd16d5f8cf9cf181777f25954b91acb34c7e688d60fc78054d496ad8d6082678aeb7ddd87b02c07c3fbc627ff44bd89d7a151a4ef01e0a9066e19a2fb6271f0a47d7409fc08ad9990e5fc9fb297ee72c50a39bb1302273cf7a042a85e44d48548d859790cd126fa64bb72cf40beda6b651c7e957b8cbeaa7248de8fed106ccc3106ecc1fd0f91584dac294e0747032c854e60dcfb6ff82b6f7df1ef478a69978a558df0b1021fab6d84cf9f76ce0b574768ce12f5d3d44cd54f21339f7189532f7e960f3544a53c70a7027b782089904ef763bfd8d538654076c822fc0df2b1f7cfe297c9f260371023011ef3bb191c0772cc0edf5aae1897e2314988b1a10ba503907fc1b49cd675d766c65a12bd60bb7da104d7fdf9f2987dfcefcd9a27caeb56d2a564b64d1e86d95fca84e6413d1fdf716595ce476fb8e3c3e71c3e574c5222e706177da384a3c21c4f1a418a799513ab32a0c315916ddec5fb80139a7fe05624538be2130cc26101604504714ea0258672049f0f432bda7c4fcde9337423203e1d6323c090e11668470bfd4a2f910ac5c2c15739f3433e6d38fa8685d4ecb2f837a9282ad8c110ee083daf05b0ed7ec04f4711cb1d
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = e880d3f9d8365b9f6e1bf535b95344a882d374417ec91227c73821268de36aae096d131fb3be7343b5a9251c9fcb5be15cb67543654fd3f43474e76afce28ee19756a09fc0f3c57b82e48ba0f042b68f1738d863316521591c81778f0a44c90c7983a101669df94ebd1550481580fdba9aa2c22a4ad4a45d65a8fa1d1ed0c539
+S = 486292eec1aff1481ee618d78c8f28d59aba6cccd74d1d0e82502d1b27df2871f55348713ac01f9ea9dd6dbb8150a3df926326dc136957f91dad72104f2327b19d3890155cd5f018464c7c2c4c3509b2f47426b119fb124046180b2ec409c4a59da8098baa59a97a100c7539785d893932b9efaf2fe5197220d1706b96ce89911883cf50d96e1f8290bd320f47ed916f9254b9cd4be55f85dccbcd0c5731b2432810182ddbd37ecbda7229e9e3bf46c7af5878c8ff4c96f55bc0c46b57a88f8d5e756a682bb279b1672d43edb783b8a4eb4c25b42702dae46db934af12b7fd3852a5a2dbd307e4730aa1c993f5054152547a8a76ec07d47e296fd55b6d405481b9283d4fa2d262a38772b10da63286f009208d6a98f4174c2ee64f790dbd47c2508224d0a96d3eace8938d719ea730f026b6e7deb0eddc967a68d78b34eb8fb3138bff69d484203c5b7c00bfa230a01957911f5589226228d16080003fc1f7b6d544e7b2a46f97b70d111ee1d846535a84dfd43c2b42a90bfe373d9319846bc069cfe2ce7a23f41e0934c97b3964c2b892dc2f66231f8b6185ef6570d4ca31841cf9b562daa5914d185aba76ba58d66592f3237954424b103dfa20268f049c9749330084d007f7c2cd5405b1b1da06a75662f4f7c280430dfcb9bc37bdba64200273d13c319ad247ad7e20ae26920767ba43b2b1a02ab22b188fa5a12108d170
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d0609608648016503040201050004205ea6db376f12859c355a917d06abfb3f5f97736f5bbb23f71ec1de277ba047f2
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 1179b364278cc399916b066e7ea2adda5701135fe737fd3cbfa320e3d966e3ad7bbd67cd5e8ec4831040969297d0b9f3572150cb36940c9bfdd9abb60105bef904e4b0b6569004f13f42decfa269c54bdaf9a72be8061d32d091f19840a2deb77397960755bb0a4ce81ae50ee694594aa8311f6746b4b96b0073fb6fdc65c951
+S = 96c8373de5bb82b7da57e144e219250dbba46fccb74e1c325e3bf19c16fd38e2a71e642fcbb6f0fc8ef77739ce1b8aff04a967573b1bc71c894dd5bb29f3de66736608f4f4383c0d5329a2a7fb127a243544acf40d245e2068bb21a8dce0b4d7e81e165086afa43929b44e45f3a5d77d57505a86651da1dd4fbe0fb6f83b37423e670e06c810db19cdfb2d1d36c441903affe00f12078b229cb368ee5e63c451ce391f1eb1161076fcfb9dc2f499de5a6b948dd2b3dad0e6cc1ded8b27129197fa0998d6fcd117c37cd4745d844d6443d0e32a7d6cb34510d1270f31b25f7f2b4f5deb8bb94b7638f058a59eedd80837beac603775c67edf03957a6ffcf7c18c8a376a02bbb9eacc175904c0b5c09d29ecceca5ddb3d8143a6afbd89a1a3b372e2c7eebff1223b1bb4f1a26c4fcb6605f1326c6e4a25c9ca7eea8441b0495f53b7c6015fda720e62e1023fb039f1e3cf1ae9490f46ff75e0b5bfcd354f91e0aca5a4ce22e64876002e304bb7eb1212171225de212e0ac5304907bc803b61066cf68083832033f4902cda8e6ef109c638346f0598fb27f38f2ef130c81f78d5721b89b949d364f0336e3b4b982b7213aa7afc9aa35f5fbad2286f4a4639cd981c7908012b4787ab506d3bb745c9a8232253d59c24bcd60f95ae74debd5967491ad8b5ae564a09a79de6438090bea658b232d0dd620e548e020e9971ed4bcae5aa
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 7a143960d5a8c615dd58a10ba92eb257888befe939812d105f7d36412f291b146c90cc8f9584e5a75d3ccb045b42f805038d9304d5e944dbd4a046a63a53becb6a294b38262cdeec02efccb918742148fe4e385df503885c63b4c10d8400189c5c25dee4f06858ecb5b8cbb2498ed6286117047d0395a29df503cefb75f7d18e
+S = 5d5f734d2700f3dcdf27489b57adb3b488de71bad11e6146dada53b80e4b5bcba10695996a7b52f89aab2f3ff43c17355deea644c2ac94fd760dc45aacb4471137a93ae4d9c4fccef44742682f0f985f26da2bc70bbacb95550f99b9003851b7a998bb1535218f7e47d41c52b79736f3005ebe8f46c5d4fcda4c7ae36bf68ac8c527d8589bb841abcb6d0cf12a797622c4275548abfd2c46d35132e5cd631da7f16c05129fbd1647a470f73c7417ac85ff85e71c433c849f5123353e49ce5d6bfbada544e4aee9887262a8c51b5cf6ddcfa15aff2315ad910d74e92245945309f71815dfc23d4b830536f68ad444637a808077650590407e25923247aaf53df43fa90d465ee06d9a9a5a7ae86d8a2180d70430e4916e7005ffb4858712edab095f8a691e2260c3fd56a4311dc25b4ed8c4ea0e43e4bb44ca26ca8ef674019218af0559de44bc0cc5f9463575ec28f3fc9d7a4d0e9b00972044b01187ca06d0dc7f0c5ea336c0e2290e1367d12101f293dab4139124c217cde848e7e4a0f15b3d3805767f88aeec07bda40dd23826afcdca5caebdf54c32021113d711b6bf07300a2ec7dde75d550c93562a30e93810c9ab3ed830a719e02df7dbcd62c4316692b69ae722a01c462e5cbd31ebef67602fdcc9580e6e326d77a4f2a0ad079acf2c2592748f9dd7c7ca7560e4cb3e7b60e9906b8bf02fde02c9c5e0645caed699d1
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430fd72258dc3162b6f2eb1784384443649d457af90d1c6bd30c443b7e3ce562e7d7e660afd677d87d01695dba2597a886f
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 8b48c7483bab7109f4d05b8cee9338be36640bb068fbffeab94892013ba9f96c5d60c093b144b229f3b6f8bc46d7858ac0f9b197295323fc00f8f582bf0a136f612ae4a020342dd883293258986d1eb07e33a4d42735e7725ca89783026f5d219b8f7a9810e3abbfad114f896dbccbd778fb2e90ea0a11f4d640c22d8b41a127
+S = 5ec4ad5490edb3c268798a03c1fd36d43cd64e6665ede2dc2cd77d833f15edb7b836fb7c31a9a6135b4ea1c84f8ea7513883d8d38037d7f086d50d69fd730fe300b5c0090f4c7cba382fe27f7ecd56a0df98f6b9e656f11169c717fe8636fb2cc6ecbd4a44ea73f91b9189b640bcf51870ff97b23a4dcaac6e4852a8862c73f80f89e25daeeab317dcc570fd7503421989334ed729d453e2b372a58ef37fc773b25d6911aa52a11d516d1011b052c0f9f33306965525c4605884980a2ba24deece8271d65c1623cee181dba8f953a577d989e1d7f6d5393920cfdb9361ec22c10bc85926cd37f3289b1efa6ceeb78e7a1d1b54be2865aeeaa9dddd4aaa2c72353338c247411463af28004fe154b3e41fc88f137c6ab9c240e98f0441237111f9fea9709f41b45cb601d91ee24725a62e0f04a72aaada19b8a25da14b86fa2a5c7f4a359fde437d7a2b9b6553b6dda023e03d3996dffeb8511eb67959c2c647e28f8e9c0c17e412308105a10c0bc4d2820c7d6acd718c1ff38fd1e27db4dc07d2f12f45f2eb8f414861bbace017c6bc4ac46f815269f68212e1c0a3fca93622fda40102194efc58c816146048d49af8717faa6e58251db269f1fd075816da19ff5a5fb0a9ecebacb276b3bca5f6050b33cf50e065320fd703ec4779b3488f1cacdc6a8d469e9f0b5a97f7632efc417bc9efd2ea18d768b27b8863e753588dc3a5
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 9e1d1d96ec18b95c118a04d5d8dc554d705565e87ae1048961110af3ea62912e0cc2612d0150acad9d64fc60dfcf694bc6640f6c65b7bfa13a24f5c5bc130a1c337babf1cca58a7ded33530bc660e25a2989b3439bed9a9babb1b45b82279dfebc4fe32b769ebb94a8fff31eb618284241ce39b3430bfb415bbe2ffd6524b19e
+S = 728ea547f16aac9bc1449a5614fc3612292831c3596d2897ee8426c04c353f4fc19590bfd790660833fce2152b026327eebe9c934aa8db566bf63938486bf8699bbb6f2cc7882ed6e9e9cb2d3b0647a5355616604576b12d26123bd60732b2e240e9015a7c4044a0ace6f18d522ba55bc9bed1cf88f94680150d05d6a8bc58e74862f7588993892859f88c92e6516f02d57fb4475a4c4872a211ee03d5152b2111ac0f46e9d826f1dfca27a1ded9888b8a573e6702f116475a93cb2d7e6301ac8742f3dc2c48403e4205082b7e4f8fb21b814c6f94634a50e83e4a3c0900906b162621360d506eea63954581771c72b2abf6bd5bf0505e3a8329ca8e1af6b497ddd7695237fe454b8a06498e4308c0b7f79102ef07977932a57927e2c4dbb3b1199ffeb33e244f536a19375fb5ee25279b425eda4693cef0a4904f8ace80e7a1916740563e4fcc18ec4356dfd8f351fb3969b704233e6c877ce339e7e38e98e0dcfebcb0668dab057171e643b6669dc187f9ea8dda2eaa295b8f88a8ba8f4cfb579d5d33681f0a306f2f20821b67613e18545059b2f6e8049770fe4b280ba849ba38dc6e70949cf6ca160910653a7e3a2c36af5fa1eac778216ee33a60e67dac7ceb7a35cf6bd926e1a16160e303e46afdfa28b018a872f205309035da90752c179f8d4de48f671c08a6a43f7bebd4c49391514783e6989897fabbfdcd87f196
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 45036afedca29e7386c707f029cd67ba4740e7eddd38146d8be5271ef46c895868f19695c1f5a26d8ae339c567e5ab43b0fcc8056050e9922ec53010f9ce10b869860f88d4fdca375ecf3a6e65fc37351cf33aac75f067fb4588cb8ba383e27790e95c3dde5f20ba4ab49255ecb8117ad14dc44ae6c09790175980f7b930077b
+S = 634e95db19d75fdb681e468e2e9f991ea38bebcd5e44717148be6c79625136182c8c3b136f09529d3f95e42d4da796a4b9010fdf3d3a483e5c78ccea3ae200a382f1c690a01e2f450dc1128c014f533bae31237d48890a5bcfb3996aecf790d18e6601d9b12022d7f134b1243965727a8ebc1479dfab096298a116440818aaf961ed9aa730e3df72f7d115f57e1294ff53549161b66d6f15f3219323fb067bcc492e9320c7b706613cca0ef030aeae3fe14d04dbc2416ea6d0ef89ac48e0ba83c90e33df7dbe215da1c7c70bfba0cf1ba2ceef1900c76c9216d9c5db17c9d3e2401814609defd932c47b864a65e9c30f75e63f2609ec2416405ef072240092dd23f835fd415d190eefe2afb80f5c02ab433946062d3bcb5c18f009677e43f5e02fcd4a330eaebac40dc788e4fc6890c1c75e22cc2e801153018b316d0bdb0adaf9b2fd98e4ba7b3507ce1f1627c006a49ed81177cbbb5a37cb952ca93655ef2fc4dc34532f9f5ce35906682a295230a0824934dc9ade9ae445d4f5342395badae4371c23635bfc03effc650595381a352cbb8c9c8a353bf795799b3d41520a966f48b7fbb28389f6eeb02c62ae21f7776e8a65b7b0fe6b10f0a498ba9d2ab503cd7e8b79fed5c1a9239766f577266a868db7b74e274b82107cb2b6e8dd04149d556258bfb92b5fa0ae4f05f407191bc28774159066857383d64d5b567e44e706
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003041300d060960864801650304020205000430cb91c002dfd7118dbc156c9b6c6faaebf14d2d79a0d28a084b2fef838a9fbab5fd2e5f9d6ee8b032d4f6588e5219fb02efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 4d72aa3953630bbc1c51a7fb6c7e0375938e8afbeef430c1b0ab56b6e226ed11a989df2cc819aa9665f14e6410f86ac7010fa2e4a18f43df4df22a3956d0e25d4c0e0c757c520482b7b9c1ac55cdfdd67ab19676989f35a435952d71ef4aa679bd67fabc77f45fa99910c77c44e604ca85dc305ada0d4c37f2fa2703b57c818e
+S = 13e21486fe238e70f645edfb21dc32ea0f415e5e260483799870d947151362a7249f700818014c1707016d71a83c389ee6f17354e20b55402f4c6036dff827d237fc7b24cfb2b5398fb34beb35d2d61b5c4d089ef832c219162484d453587869f1139d7fd3497ff4189517ecbb2d314c049d4e86dafc418c716c3e4c2803ea03c66b90b93c620aafac05e4252212200dd1448e34914da304148d1466e5e32edaf6743fa43c307f24ec1a0d46b4bb941945a2ed7c02da826476522cf7fe329268774052310d4b817a4058d9ae6084b4f1428ea1fa5a5dc0e666ff9466480b9f1d6142890010fc2ca3ee46db1ab084a524bea1c27b89adc87ceaea0a1d9e8d83358cfc20997b8c94204c80871c0e9da89b224ba42181743b285157d3eae18f19f8a38a102e53d2378aa241b5300a20592bc487651264dcf9084c3b1f0095e848f1af5a940a25ce3d0ae660ebe9ea09858bb366451fe8f4d1dfcf018938db14bc4efb1c4a2a7f5b08facbf81256ffc0453e4ba14744d1611e85cba35baa9302bbe959dfc2c0b96c932063fe40991c2ee47bc1ed97999f8e5f747f8138691db117784a5800ad4d210caebdbc3ba84e8fceee3bf59ff163c7ec9c0eaa468813a1fa8215464f390fc62d45993db71a7e56c4a022fd4ee377a725e87a2415877a6365b086c76bd2702abb265ec3b37b198eb84e9ce6e1037848c10bc132aa2f8e1af165
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 709abcd4c8297d89f8e4a5446dd32ee612838200c5a990950b091e21029661d997dbcb35f89924ac4db2dcbea345a038281b2bb49e425f5f0af794ffacca303434fc77fd332ca57fd0323a02bc4c963d6878c5d375209c1d6cfc052aaf359704afc66a356028298aea2e6817a22e387b3861f966318c705898e01aabf11fbfd3
+S = 95fbadad59d07287451d54b9645279f6fc62ea2c6dcdea2d49548a992844d46b559be0328662c2be146e3812aa9bfb073ef21f2c73dafdce8297d70a04ab3bae8e0237f6da726621da82066ec76afca2340e3ec256ab5f3e0bb53833c78770ba95e39a7f844e9e483a6cb7f98d496e4eea095f08d809b422dada7dc779303939e5dcc644bbd0b22a339bbee4a9203005aa34a276ca5c1135418c705b8d70284ef279f49421304b28d1ef8606ccb2c9591ef36b418ff3f52933ce1b059d9a3d04e483c2baafb719131f29f1fbfabb85c7bf0b979ae3377a35fb877eab9dcc630759d18b3974a999bfab9704953d661ca6449cacbace130869c2b0751d205c5c6ffbeaf3017e9bce964b2d4b6af2ee8bc9897b6df0d53b061e89918eabc9ed4f46da59748576e816c5bdd0c847a411948d43509e994ba816d6391b041f23c9d70d004e9d3c09fa717c4531af5b8dca8393d28dbfe3b07d6a88da2383181050bb033b8f21546432f62caf52cfb364e87ae5fea1c6e2948e39aeeaba89797163fb2b3bd35d8bb8832218a5d931d351e9cee457504ae70c09b51004c826c913cbf61f570504951e02b1e47e9ab3dc47b44559e77d79b734790a1faedef901d267129139c66c992f039ab42d15635ca1ced47ab12ba87e12fec8bb574c9dcd94e7c6ef54a75fd568755042e8d928f344c65497b3183eda9534db97a90b24927d77e2e3
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 2be1649aab8e12b337a5d974ebe354a0ce3e74f4fc76c45a05edf16090b889e844f60321e86000b6c822d0455bea3812243e72fdd61276b1bb9a781f565db22b488b63a47090187a56e92a2bca36887fc891b6759f1f167d52e467e73fdc8b9cfe478d0c8c44e267a9a1ef107ef2cc4f83e04846a0c42d269375c5a2915d9ca4
+S = 11a6268f9ab602dca7444e9e821e9e9dbf2ff6f875f255d8dc202f953d91d6bd13c74697c70412131091a062f7511b06264d083ed49b24ad429d35e9fb02326fbb2b206dada13f5aab60b5b3db5df6b83e80eb946e199206dc2fc7246ffc6f663217fb5ff2ca14eed28a58ba010b5ce47993b4b66ff00bcd20720a4a6df35a81aba6d277b2ac3fe65dd7089b6fb918831c54165aa833fd84fddc5350bedd1517bbb180dc63016a10668add62ce782292af053a1419970cce6c6740d9654b62d836b7446db56267e08aa204fbc3d3352c196c6b757cb08f137b0653bf362249dc7a7162eb3d82764b51b8f7676401e89c3437ea3fef7b727a096143033d2dff653107e6bf20f9586b2ab75a164d5ab84cd0bc6e04749ad4599c80e4edff189c472b02c91b31955284c42aa5390d83defd8c4c24f14e2aa9668fcfb0b683fd7702da5330e73cba32b77a1c197c4385b5ba5e0ce2e5a3732838fe136020b870c238ddf5900b662dbed59e9664754b63cc4b8fa3766797b2120924d712935f4a591e61d292782bd6029b3eb434e33c06dc53d1152471c000dd8e9eec094ba6b3dd5d5e71e23039480df29c2b00fffb5358bb5628adf89260445ce4ea3cc4a701af52d382ed2e9c1db9837c29e211332f9b6c176630f307c5b0d0e28a1a09fd285ce2c12d1f18269cb1a04e5c1c1740fbe8af04edd32abffd09ca5641806520eab220
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d060960864801650304020305000440a6e9bd72eb12cb01af08cd796b9a5d7f70e34e1c142af67f862971169f7110687017d74eac1c5d45f013743c20ae189d7c9c61802770a915b37a0ffba5ee490d
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = 1dce67cb88490ddb92b9528b478d3cd681c51ddeb0a76f3cd7b40394d7da5b6cf0eb543e854e07cb1ff5f2b3b58e53432bfed58e180b6ebfcc5888ad92975fb032faaab4baea7d8b7efc6e885e21f749471d1bd4fd3a4ce6173d8d874b99d4e2ebe3b254b08635c3b7b80e31c9acef90df0937d8e59cd158bf4959498a4881a9
+S = a73f90dd956d119b2364f15b1772eb3398cc0dfa717bef2d0180ffb42c5a6a9f6240e56297fffc3ec10b8527678e37c126a033cce08451a5052575ad1e471801df563e447e57626a09a5b218aa5d1b3ae3dafa8a43e0f5b187f9d11333cd07a52a9b0844bf61f37f9107fb9770ecc17f1858767475e9e63945bebf12c54a25f9759cfa4b11c605d41cc2b7aadb786a03fc41146ab249d984f6b78c89af37a6d788c67f0575faba520cda93288479f02c83e78122ae5b88ceb6ecdc429f5e8cffc9e1fc78d8c4e638c74fc905a2ecf6fb2e797a1d8b86d458d0d594836f66b801445e743d33a5f936138a1c18dcd08f6a826fdbe71bac84dea0884e5310316d9a28b50d5f40d441d5385db88f4934b4fb85538e9838ae64f9055da047f8d49d432feee879301bed3cb7c2774179fd4f76813284a492d1c89df758ad141eab289c504bddf9934753d94588c2c9fafd69b6b261ce320c103bbba0842e9e2e14fd88d17319f9a7596a55701c22226e255d06f5dbcd432a930758725ae73adce8be417d7a94a712d5c5b3809441557b348720a35da7de59923e59c92df63de405fd913fd7fbf3407c72455d3be934e3d7a878bdaf88498842fe533a03387ac4a6271f0c3621c33424f610eaaaf6878fc99660b2f8833935b6eba90636eeb9b9f52fc0f3244183e59caf31d890b22cca748c80abf9837808b4a1fbb9cd5c9a9b84a2dd
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = f0b048e510fd9d75f3d7bf3f460ece324aaa452f6e2c2d6a23179114ecaf3137b4017ae16523b684b6bd819d45c87c94e59645e33913a67b824a0c63b52b3ba3d18b41606f6ca8489a7ff031e2e73dfcac404cc0cce0ab25565c2a0db04e8d7aec5683ac555fdc894824f64246f2783446af430c501ba62f4756d15907a38d83
+S = 05eb7a32c9cefdabc9208a080b7542bdd0e1e2e4a8529c29a7529527207a0b5105464d0cc445e7e64fe2a9be5cfe6635d4fc1ae7bb7ee36b86fb2ac72ac7d53af6b1dc6df2c85d9aa3513ecbce8ecfb1926332f3119a4bfae1b01b2565376be9872cbc7bbfed88a4d2e67a78587ca53e09863bf21ac1350bb38e009c3c458d2df736b1212e7980d0a3735925cabf39ad4da1b98e9e7a6e4f73aa048d8d686297fc6885e5a939e3195908e17d32f7e78d22e9eaf3e9373ed923f0b2d6b45497351cdbc9fb8ba0aa912223121a24b2b44b291743bc3ece0d3911c4d54ce82f883493805273b0fbcc964ae9529b83e6f22d0aedc8b6f8b2a410abbce970cfa44e30c9b97ffb312d5a53d904d5e99a86745a70c6c9f8f3303c31b39dd587211cc49c973837d89117583ce5be56ce263976d9c19303b7d8971bd1bc0a7bfed7af8ac90329a628a85cee99a3c5e9bddaf857467a8fd3b015345e983946a1a22c4bd2c18e3af937555a08dcdaa055a8fed0e06ebf19f5890ed0dcae6e031e9150810d654925a9347add44fafab80d3bc8342e9f41e60ab742d17d368e02e82d56418c22ef10021431c00af4e21b7436aaca8b67dd7c5b1519ecf0c414491c1bd8a1ab3fcb1bee7d202673c0a080f56ae2966605132998c79ea59bc6aeab631bc0064187f11ef3273d5c6459ba6ebef569b99ac751ec0edc37492c7c563991a0dbeb2710
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = aaf54244327c90f0aec7add583fb42cfae696074fefd5c9a80d9dd1a3b3d33d31eaaeaf137479f6f268313dad0fc7e5858a026ea4b112fee1a4eb5e8ce911881f77397d0e55621d91b046753019436afd98e0455f44fc93126ae106e77df4d811b98716aa573bc367794d2c97d8b12da1b7b233f637ccf6b8c3f15359ff179db
+S = 0524037b884cfc8ed0047ca0cce7f7cfda9893c065ea6a1ebf673398e23a56aa4b0a179f1b776a3bb716ea83f0f9f863661aaefe7f50da0d714d9cdea2408a09708d50aa4c6bc6ab31240341098a1d8951c82e4708a5cba44d0d0b98b09dc8f8781ea59d9d6dc168bf80d50e67fb53763aebc6dc12b19ee6ef47b838d58f1bee5f6f3a263a430b22f633195ed0d32a92c08b2a4e75807f1b56edac08a6a87720c611ed497dc184974ad7d3fc17dac4c409a44c3fd29a35259fac0ac2395f81be0fcfedacc8044397f4fbc858640af552b2cab5f85a042d41050470f7fa485ed38a0fee6f9e935611e33b50264ca04f8fc1c6e15d20d10b023ae7768b0b87f99fd298e7663fdaf5dda0f61c019ce0516daa8db07f46dede1ad63f8839e58e3c33e69df238c3481b7ebcbeaf448b986ccfb09b3cb62249ecea2315be42cc6876b7ad17a79a10d8bb4cb83b7e33fd28218b58690daf5de8da3824bae1bc9d84a8c9c09b5f4d67497d2d5b215bd530d41decf24d32d1c73beae4e6edd3d2859f11c7d8ae60673c94f1a233e285aa2bf8be8de7c5791bb6bc624ed74bc1de32796bf656c744dfa9ebc3958b71f2f26a9d28de16927aa2923e6b897c3c3c1f719b3239d1e59a136890b21efe97081cdcdc69a39668791fc4089fccb694a77a88101358ffb961792ca3c41b15bb81e1edd7fe403ebce86ff17c5534d441d946b7763806
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 1d8188e62be3759b150e29a7b864be80ba2f00e747cf6caf45645f91085cc25d0ae6c4c55c97bd20e4dddda23d8d03af33a13e082e3576602ccb4832d10f7cb30de94cd2ec64e92b8c7f1bdea66491665b313b153a2d6dcfeecac1e5709f113999d8abc4128b58dc232853a3d50fcbc971beea4a4883b1691d6b195b3f295a12ab6bb393c7e3dcfa3bcb6bf7ddc6b22d4550657ed311590330172763930905d38234c89f889d85bce48f451b21945cb980e25d8de6b6fcb2828643f5695105a4fc5705cfa9da5430f6fd98af78b2f2a255eecdc268922a71dfa3fd65c6645c6204fa1afddc7f009e24ff973f70accacd07ce05b1a3e352b4cbceca24c691c94acb40f9ec6f1964a3c73d4b50ad1279598711ffbd1e2ba3e283cb33d0189ed5341b2991aeb6ccf331e23d49f473adf4524a50d876089c824488b1a9d9253d9f3471ab73cceacdc169bff8b6ed6258a940ad03454ee148c86376c6c35971db2a4901980fdc3e78d1149aeccc32424162bc1fdf115e5d2a138b914397d3384bd4921ddbaa251569f71d61aace4b5d947eec59fe57827cdd38c5dd01a0f7beccc0f80662073a52aee4faa558a5c1e9f98327fe91e29340f678c8734e5790994c1ac8d9da22b57cb2bab896d45a2eb0524cc8457275dd61f6c4eec4c2f697a07d33d07a46685c95ec2658259a7bc0dad3d9529ac5485de5cb014e9b7dc7cb6e2bf781
+Msg = aaf63b5ed0e0aeb7ef3da4f134dbc2e8942acc27029e7366e5556f51c9face8b54e98cf37c936326f824e445f464c7f809db80b26c39133766f5285c0433620e0febed963e48561bab4ea06984c094f103415810a0b9439485faf07c42a491ffc24586d07dc52fa1f002fee64ab7d0db69a27dc804e6ad832aaeee37eb130465
+S = 28cf265ebfccf2400d6129058b7168cdd9fd44f44a74630d8df79d306b41a82d9ff0e7e08ba01d31514ddc3ef87dff19321346aab5c67959c551695cfdf04bfbb0ab74affb9edc69b9aa6eebef1d4fb7b1ecf7fa30ad5834136de2510fa774a24799b6f5e6410f4f14354c010f7f9e4976d7772ccfdeab7eeff704e9531ec3db509c1f0913144a444dff8e36f9f50e6c2c7a693c5ed440d95b721664aff953a18f033df5ce2fbc2902d9fe4644f10d50f69abbc7d2f58a80e6b6b4c94d75fa53bdec788315e87c103e81dff4c5cf7c5f1fb14a3019cc89a871328969ba9d12fb14326458ef1df1dce42b02ad17db4bbc75161e66aecbdba7ebbf1709fb208642e3e1a3c12738440502cd235d6a43a08d24f6a397b0a5b86d0a8456e939d4422934917905b3772e2c5736ffc0b3cc8b8bbc1c9629ac37d54def02ec83a106a6537adcb6559ea3cb2024a1007384e604fc64ee9fde2aedd129348c7fc34b240dc841fc45b2fd2c9ec16264b067f139bba8f3c31bcb4291b71e590bc953fd63d1ee44a901d47fcba0d12150ebde6f50209646831e10cf3fa7e129e5504fbcdf4832f5589f191925dd85ea7d11031cfcefa5ed4f9bde552c4270930204d37c37faa8dedcbc2838a36fd425d2bbad87660fbf8df20610e666a9c382b81b27b0cb172a188c46bed70dfca37563129376b2d6e78d4be92b81978031a84eee45f9731a2a
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d0609608648016503040203050004400ab1a89aa9fb0c29b4163f44d7662e24023b152d820dc90168548295c7e1b5836d3de20a9fae39be49bcc40d0c54e271a4f6fbf4050c315553dcb6a3db8b5eabefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+n = a74f2eeb83f4f87768ad1068802b453e7b9808db9d1758ce52ccc70c3cbc4cef2afccf66b1116896fa27acc8cd779b4df59757e24bcc0e69f409b638cba8adbad885f95680dc4a7423d576c448cc38b00ec0292ea3323bd1eabe2bcb6d9e9c94665eda88dae5bcfdac2a3ca71b6d3bfd31cddda0f41f14dc5ddef946a9f779398b05e46678d2e490ac28c8807e9991bdc00ecc28d1b7cf63b6f3f47961080fc45e43729013366c654e1189888cfdb7458fbd56ba3b29756087ad1a0f86bc5e1637f7c6f881343033bec98c22e5c22d91ec2576c66214aa895d08c29707e0c181c666727767f5cb99835eb35a75d44033e5fbf947f7ca249861d5fa5b5d1cd4845d4d241048bfe2b06ffec934665ce371c826a2bb4c2de1dbd115a1e220465c6eb9d26297e2f9187726926e33f6ac7154ed73148aab86813b11b7fc043a969c8b9477aeb6305a73e10cd9db0cd5dd323a9c7ddc08accc214b4a555da9cde05f3a351948e56848d543ea504071f6251e035af576e04e55725516e215ce5b40c13f4029caeee38e4183c834127c857e1a0ce52e2db2faca43542eed0fc2331980be2e70ed938e007d1ef56f103f800dac041bae43d2117fc7030da4f4a87b1161c7cdd46de4098d10167e028fae2eea05da82c687ad82817efa65e973845b5a103424d17234fa78da06984549569443fb9c8755c4627a5b04992e15c0823b45a855
+
+p = d86293ff70f21a0aaf50f3e91a38fbd29c3e84a034b5a9d5ead0dfdf0707cd9a85bc5e17c51f149c804f9feb00c2aec790e605b53108cf008e7636ff32e0329af9049e0bc48b91e2712deb4c0b1c2e943da090ea0dfe4e64c79f4242366eb8761a827e64d7fd3ae66b340093a21024418db44dc8305fcb097b942b2f7c790835d27e24a9653eb7af54aa06482f6438d4676965d602f3f1f8939e184f6ac9c9df083fb862d617af4516d824f419e11157b208009cec826538f80331286925a47da40e6317914dcab19706831ec84f58d158d945a354d3d2d1900ba044e25741168d334c5100ad408591212f26481759d46a735fa5f14b650bc5ee0e4f059538cf
+
+q = c5f08c5456b320360fa4338f92b57a8c6715fb6ddcb07c2d0ff93b6549e7df6e8d3dafc5710f02b42d82f62ff2d365fd7d9b1518eb512f55cf10f347829aa961ba9edb5c5e36c1d899b4fd462e9e89050bf7edcb20c0b54771bf22056a7f2091739878dfc53047ea7cc2af9ced1fccee39b2e9502307f44b1e8f3065aa9d2a45e1b5ee174d067a32fd3573f8d85c17fe3153736e9b2ed6a9fe068530eafdb0c42c7ca5cc9fbf44f84594b324965f537f1862f2ec303b42a838ae892dd1a59b577b7506c663638c837b67d6e6d03066b71967ce938b381f91f50fa526089fd146f62977cc41111597481d9c3af2c099279be8e6cc9fe7c64d394f9298b44a4d9b
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = e5f707f500cc4d0d36ebec7b49ded4c1c1d8fd4186f5a1a5aec2a97e9400652b2aa57ffd90243299e5eeb79d5d3900869300a9d1214b2c606fb05420c81af4e9b3c9d8a5809afcb52189fc903b74ccad7d22a9a431834f9010396db75b58566d276af935f9b7132a92c3a39d0c179f002644e502dd2674fc3c66dc8c7442f37f
+S = 84108250f5183b7a1957f5ce9c10b762fa7cf3444f76485c0b5033e1f922d45ca86feb96407efcefabd35bafa24b1f3e5d86ffdced1c3757e23017bc2a816e940391eaec9c2b1e01c1f29119b4064c60a2f5ed91162b308e21f70374815e916f134f7e8907a8fc120dea9cc15c53741ae1d1146942a06d0e1d297ec0fcd1e7024bacf58b0b64ab63f95ee3e3f3893a6a892c8c949ce1ad5664196bc7370411d6c18ac7b3998e5d9d35e6c649f9205f0453ebdbc9eb6da6b4aa549b2af507deb7ac776a89b43b87e01be516e4ba36cecea8fa598321beeb7eff47e7561b52be6ca99fe8114b9be68b0f77c5d8769c35fa04d5c4894d331e7a1d65f25b44ca95e8074931bda83dbb36ee622582112fd918a732afe4040280395fa87dd566e69b3668b295a53aeb3ade6835b32dc8bde3e59f6b6ee36322b39d50c14cc98f7af082468be675b73548f5194dd4c907d99db54f785097cb9ed28c812bee694ec4ee85a8d41501d0a70d82cd8316c2b63d06e2e502be79b5a1f7c06735eb5b850cb0562a117972f171e04870caa751064db6fc4b2d64a2ddbdcf1d17f6952b630b86d6124bf6a7449cc57ed4cafa192756571fcaea3e0a52a92baf4d18f7b61ac404876b1f7e6a53498bb9eccbfe94992a1f326017cdf91039266d9a3deed3dcb124ae6aa96402f80372881a207dd833b4ae38d9d9f5ea2f30a4fa45e566e33e1e1388
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 5eaae0a318af7626f80e9c31a4e7bc127d24e823c80b1efc0c13cbe7baf78d95130a3d0f47ca2deedab7aecf4c66d602f9d180823ef1932add8f8825a35726a7482e90da96c5821ccd6ed867472f5010581590b578cb6b71a46b60510194630cc3bde1ee4dc9fe1699db21e1db6bb2a6619a22a4bec22c3827525b541dd9cd2c
+S = 0d5434fa33a83f13477d6ebecc596e1847218ed9dc99e9d75a175a85d3bebf47ac7fa9b537d48f49cafc12ad3b239a7407f56a27b9dc4ce222ac838a6bdffe594fab2c6d0bc15365a3e90f6765e837ad864105decfa723101affc6c87dbfa0cc0234b9f1fe033d34bd9a5c4fca3a5e228b3ee3c75bbf000a6ab654c2448a43a6b4d2439ee84bd125fb44688a942e847dba0ccf781840a0341516080bf7dc1ed725b566c07e846840d02ab8fca219127ba0f7fec701c79a1a8c7e1a3db32985eac37a2d15b8e22ba159a78bfaab05f00934c95c1aa8d9b350af9ee17de47a69ec25a05572fa57ae33d9ef1d7f1f6d149870c96b2c3f266df32e1e9ff28c718bd03d1b1a7ae7b63fe22a82c2b7879c117c7d16a805efda0925c02aa5759653dc6cae6f1d5ab02d718c78403e40ca30a9f5473777927980d142845178535dcef705d3ffc0f650ce17e8e984da4bf98a78c0436dcb00f96c8aa5f893ce4c2f5088d87d6ce2c90b09a107e3431c0cf855f641d964866b56f409e9bc7bc6147ea3838c1d78c833c973f2f3040872cae6d226aa77e95ac907dd514bfc3534f76621c4b663a0886fcf34e5f741a2dcad200943da40b38da72d6d60eb3ea0489ba6ebc1d0a5b19c966cfa87d72ff8ced17ac770f4ac20c88ccb2e3feae775bcd9747a5c87ac38c7294c7a99c04e1a421b14fbea33dac05f7efa2c0fdf6988cd8f15ac6751
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = f11684d68056464935458c80bb76ecc5ffb35a4c35ef4cc51d7c1c32847fadf60da0512f3106ea46858250c53b0af368ec6ac27695364b51df03234ca3d688beaddd4555c05dd6acdbeccd1fbbe074dea107b4405599355a6b6ac7d1c56401ec593527ed344551a2bfebca3742e0b74ea6f4f9517fff54074a1bd066f2105fa9
+S = 61caa531f63359df1779d5765223207864a01b218fca9a8ca97c125987b1aeca6e0f667276421e708f4f6943df074c48b58384cec8e773e60b4d2c2ecd9db62afd9ddaaba4398d98618ee89c6ea170ff53ad6bc0c08fbb3ec07954fdcf980df778b36c823f42844be7793e78d70248139fd8f6b8cef38d2f5a93e8c5c0b5f5f879f3f929da5b7d9d9727c808ece9290570051238b75dc13decda4e619800acff51f99538f97db8dbeeadf8f54bcc58c06433a3e018dc9bf8ffa876534cd4d2f3b5e88021e8141f0356d01f5198704ac9ebf3d4433f92e12afd6dd6ce5a734800fc874a0f1a4281f7120380db8f27d2cc54fc51291d68c2b031a046426243d2e1c34cae5302685e1eea7aee04d01a1cd4326297fc605af8a6ca1943dc43d9cacf9e713b9cf427628b54ef0da3bb13eb64b9dfdb9e173176c693453ebbcfeeb9b637bc9bfa401fd63f1edcd6fdba3504f73c7f2305683c8a58ab77250813cfe94fda23da973d3db920e3134e94efa3ecb5f43211b3d12c2ac67d7d43fc7237cb629bc8b2bcfe8593945feb32d3a9d2828a2e16efa56111c3d1e6406e8a738313b615a9ee30edb4d03028b7ea0545efaaddcb2a941129530f67e1d9d870a529c6c649ba7db4bf2878e268f7794943a19a0b9d230250491a870cdcecf971bd7e66bbab6a6e9ffaf5f8b727f00532a609975c78820b48b0af715ecaf6867bebfbd708
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443021300906052b0e03021a05000414f3c22813bf0da5f5ce5244a03ccc74c41a51caea
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 6b7c63bb3b14afdc085c08805123108fef29976a4c856c74d34473d1a553f86d8e9f4340377a6dd19d4172f9c13b86eaa2c5ad6f68ac8676e2db67cb3236af26c7c558688c15cc225fdbfa57c5dba883dc080bdb91ed95d7124b0eee8704e6a0fd37cabaa2ad75d63874c921c4c91e61863cda362e0e419f4dde8fc10a8444e4
+S = 2980e019c0c7e460c720ca8e45e8742a14a5c712db17cf51e8a5fc7ccd6b2878c4c609b1ccc6258493a965a444bcddb6a21dc129119f4425d1a707555a6b50bdbbe0cdbdf0abcdfaf8cff67c2056e2e9df573f425dd0f56fb1ce3e8171e12ef6e9b0062d5b393fd61b723801a9f57bd8dcdf01d0965641607e3c952715a729e71622a3695e16e92b7f8028c3ac25edaf3ebc34bde80113fa8d4d4f7a56b6aa0100cfea550a220a22ed7b24d35f2e89ab0709ab7e3478fc1a61f94b6726d5c3120e2de4cd8ea7f5c5651f425d4435c1de0696babe95094397324711e4e7892e287fe8131f976f263c0ef209bd78a248b1c72813c963ebfd52162ea9a6065aa32b0a97bb33eb39e3bcca888e6f92afb8f3891317bba4fbaaa27f638bd7900801683ab6a4f66d0101246c1aede70ddd6367d255f21e86ee48734df39549501ecd4367f6b59e386a9a42874cf0db6af11c998d29a62392d1bcc40f2feaaff847aee8bce8a93af3f1c0280966f9836af3098c10260dc6db8372939d020e863919e228f0df85ac23f67a5cd84e7a564bfae74a307140e636f10681514383d0b270d03cdd969b5e2eb5fec36af874b1d7f387b7ba69daba036527474fcc803f823cb17734e8faa073cf470ce65e480bb137332422a55d3bbc72a148758ee0a222f8febe8f8d99c1051df894132dea5b0387b5753719253ff3dcf94b006f2c83e06b4fa3
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 3be0bbfc2f5d6da14c29e7dddaf4630f902fe246117bce54b661dd248e43384da392dde67f42419def7b3a0307921d2a66372372bcf012a089c61930273dfbed0a8a70be4701c8c353cdd1a00de3fb19ff39bae0e1322caa5f5dfc881d608675f72f3b2b8d82473cff85725df5d14405e39b6d378b2b649bc3904dd47893200e
+S = 632af5e0d55d9eb7d4230c6818d1a178df225d91919423df4168a3e1fe2142f1f26f00c5666dfe6817b2a27f3c2fe6546ca747d74467f85ac0b73b8e34639e8448e0a560b1bc3ec827819db0df2d22874106205f93dd0d903926ec0478a5361e7a9878c6974a8c095d1b5779d783823d4355ebe24762045229ea839d05a177ffabd39738488ff449111238397da1266eb97ce6e3c63c7cb9ab2950140ac4a94dd148520dd67527c48d086e20bb6e18a26fba04a81008e35e0cf04388eb4ae9a1193d4806bd2b771117dd2ee2f349b01805dc056e5f0f3ca4df9c15562d6e1c9fb611059136fa581125c383f6cdf2ca7f7bdfa6cc8d7a2aeb1e2ef7799941f2c6c8a34021be8c771ce3e37aaf31157f91c37ea9ee02e6ecd3001ec30bcd6a45258ec7761d967798402ad5976f22542e5604d58627fafba14bc5bf3145861eed0165484286a2bfa0e17a37710b3a17bf9090f3493c81ccac46078084dd2eb43456cbeac804224083b5a9bbac414a57332086b8e8b0881707d41d4089066e36469b0085da76c6fc16d2486b3f7fe31964f928d3d902c3d5598df2f72d1a2d5436779985bc9e7264d07448f792a7f394aa36c9534be9ca7f431e90729481d0397ad8e4db9f4a429f238f7e1cea5c03795d82beea3ccdec38ee4b727272a9eb520e943ef2a1ffb10cb9e8147e1ea0b1d3208810b891b37f9ed8722a93328468b9fbcd
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414a42c6b6337793e971d69173bb994a17471dc3642efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA1
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 25627026d11f380f939eac2156adb1bdc2e9c087bb318c782b5ae52f0224dc887b6d2870a0a5c8f81082eaa800f50c15805c61b5fff976f312a3157f71bb6ae84262646c9be95e0f4289ffeab7555ec6746c6ae973738a30f143805e72de93b405a8edc2c9d4427cb01cb29083b5f1f72682a5ca1e880f5850a2ee750b75a015
+S = 3c76bc9dfff017dbc6ce8cddfb1066ab8e669761c9a3ba229229eda74f05d7790c0993883aab90d16c2fc358a7117f8118c9147c69810f2fe1d7cd4220c5df5bc67ce3d2abbff139083bb6d6c48f6122f71b30f20e37e39f760f9c3b317bb26d6a14fd864d97d13c9a1dd7480c03727a6b6fb2b1b74340678a68c0efbcd36a39d42bc8dff44eb78d1ab4131b80eb4cbcbb6687f0cda506320882dcd70c1839c653a026179a0615175660fe557f45867fe6d883cb808db01ab41efcc0cd2137355fd2ebed412516c8003213a523068e47ed03e58f529af079a5f86bada203793808d0454e8170c666b2638c248df1e6b9a0cad05a94f9710d7912d833e3a474a58b450e10a22188444b18dce363b1bb3cfba548206fe448e84a608694f060e71bc17e50c1c777b6fe8f0d2f480f154b90ac5c6ec274a62d23d72a263cf0fe797c5a1b226d612c2007b502b42c9cebe5fe27b5e2b731852ab7db8eaa8fdc005072c96ed55284cc59985aad5528100062ee96c482e9539cc0b5a5e30954ab4a386beef0dae13c681ad8729a4b3dad39739892f2789f18c5b517ec2ccdb2b9d539ee51546783e633efe4d22363858090a0f501ce4acb8231e2515bb06f02ff6b42ffc62b30056f71ef4ab1952b614c32711bf8211f99a97bd3d3c5780142f3730e7763a476584efe9d8bb8839d27c405f52306f3d4db3168a094316c699e9190479e
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = d40724deeeb76472778ad98431d2e2061239d0178df747d81349e77cda1e2c9fdd1393d924a1ff9245955a182bc17fee16f25868e32243748eeebbbbf54a34e9de7346483c250e94ae0fd20b4984e3c39773c840df999846a7f5a8ec787c66f2e10f8554beaa5b1fbbde87841381d62b9ea468ca0ac50ef56846f738eb1e8c63
+S = 258f159cb8bb860c3c3db9d6b59a44600190f0076d1f2ac163b52081e01fe2e7423861ed9bb5df8b40d4d1354dd74219c71247bbdec4be0e90910f827da0565b6d13c5f60db49e0932220c1861dfb3f0b13a5fa74477aa329ab24913ca918ba7cd4e72fa532e044910f6a72cb525853f926b752adc76d39bbb9a265206c9820c3e331670103fb82a9a0071dcc48ccc1a650ea1c95341a48476af0a9b0e4286d96f0a976d3884ba97e5aa78909748947996f233ba02d6586a375dbaa81f3f00f880352f7e1842dad59733a40bd0c9393276c47b8baa99e8404b1f539d09cd6958007b297ac8c82f66fe2768fcf572766522a104d2de11435a19d2d1ad77221ed22d045a227f437752f3029f6cc55a99511f1febecbd45d529e216803b335cc206810d19804874760f66872c8575022f7eabfe437924b931d18e8156f33e6eac5d5f1540476359c130781a436b17f3bc23eac0f9fdc06e9123109bfba7d9a7eccbafe6ffa87f6c872d952e7fb3f6f2f73455d0f4f7fc63a744e7713219425e746d7d2f9564c4cd1a6301cdd78b0945debc122d85adb52b3cce920b22e77f0c835a87da3a2c9ec3c0938551f76f229b7c734242c6b78eb7ede1424368834e94d9f7df0070dd4d5c7503b5b023508483c4977b0a69e4183e83b88fcd924df78387b916ba475d9cc922deabef2dd07a3920870ef1a8105d6a6aaafb3210a7b1848b81
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44302d300d06096086480165030402040500041c560c52ba7c3dc1e996063b94d4238054241198d156f307d890406f06
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 662e6fd267dd8f2e5f0fe89034e4b0a6e8241a256dc8cd6bbbbd966421e459aad85d4ef0de0569a0013d1ac33aee37223dca37aa4ed4a0155622c2c736e1a6f65b9b420e93b5ee541f3c1cc909e14351b8411c14c16a1125009bf362e84ceb9b176eb3f62df40591df92546a47c5bb7c7e13332b6d9408e2e0b18efbdc2c10df
+S = 76070d1cc628d84353c5535dfd3dc19573a91911217d3f9382de19b3d51f3f5607c7f88d82bdca4871b5361f39b8316b45a9bdb3775a69714bdaaded31dedd9716a8ae202c0237732b935c469ba22adb7dd67f67f5717787a6bc33e303af0f341cf202f8696c72f54772bd619c7929afb2785912701e91d96f9005942e6d11fbd757239a5cafbc93ca098c5632424f7b930e69457cc8810cc9ac3b5a1d1e17009ee45887a632cab31c9d9dab6e843481a09e5a7ca77be9d3d5b0d668689bdb82e4e2e43310fbddd5774d482b43cfc1499196ca521fc58bed44971eb15d216ee55b125ea8f65439425dfe1007d0be5418113484e1ee9b1fe3ab25625ac624eecbd03ff9e1b7dc66503afb625ff659917635098442af02696feb0b2d9559c19505cfde72470d34dd1719655874c8d4c23a94d5f91da9aedfc38e96e271ecbeaf924d7a9313cdcf6f485cfb1f3107c3ce8e0fa06a326ed75732738d52a094e9babf6e14f3f67ed48a09797020c9ad48a31aebcf4fe0e0b4d1c128a0f90f2bfdd520c566559747802367e95d45cc8202a479fead34c90c4663f313f3db337cc244a85eb595a904ac9c8c213fa6e762a251a4b84e733b7990aaa92a358ef369732f2224b5d37692f48f8cf6589034755347eff0c34725236d3d55ec27ae919e6d255025e4d2636b6c07807c66751942d9362143de6133a90f3d3503d9b50f91d549a7
+SaltVal = 00
+EM with hash moved = 0001ffffffffff00302d300d06096086480165030402040500041c58df3479e243f7dbe552ec444cc92a91f478808b02c5c6b5c28d44d0efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = c65baead3c9c432956e7da3ecd9f9b81b220c054b3f6f9b79a4e0f6116a9c810bed80c1d5324455345cd0c0179b6014e4a5efacdce1261515a61d70348d11db1f7d0356914edc4471848bb8b124736eea78ba5375723290902ff41ffaaa7a5fb7a2d72ba075f88acd742300320bc030ad19107b9d6911a86980f947dc4942893
+S = 6676debdc5c1d257b6bf532f1f61981e769e3bf0676b5050a8dbc65ed78ed3b88c687d0213ab1c0ad73b8606e2e2e9ffe7ee8f9b20a532a3fd59945b9f371d13807e36da1aed420d4390c26980cf70465e3dedc22368b09117e4606257677132a7c92e73c0633718290535915c512d629bd3db35306f264c5681e4b48e3f5e63f46289e41d74ab29a099c637132d2b8a04bf7649e4fbb0a6b3f37873d2c001d7833c9bb1f4de8043858223dd005ef43c6ea6e0806d2958ead96fa89af9119b2ac16b6302e9f23c5a2d79a2d6c4bf5b576ab07de117857ad4766606e52de3b1cfd368746425c74154cd814e63ee05d419c9f05038683970019b24961de26f0312203358cf5a69fc3a8c34376774d93a07e8ee8cb4e49d3c8061cd988ea9a96973b07dc8a8b96db165a0f287df5a538304a9b05e2ee294c155e17bef1df251297213904b56fbd3770d6587e0f610b291d0be288bd744315aebacdd71d00316f9d169d542108747a10aa65c36398eee21d7c580d088871e9c7be4b590f78b8f315f92e6970ba9fb9f929af324d02a281972cf2841155de6a76b54c1316c818f9c21c52eb8ad063b53aab1b22e72054ecfcd833efbd3d0da69c3730e81d48f54cd9c22da891fc589b3b61b5a226bf54d401e576f2ce86c9b651cba2d93d63e2e3181a97baa20a15f6e584dc30e1dfcf1a3d2b69803eb84d3ed4f1e153b76f14def51
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 953446b04306756e65d0cd8bdc3960a0713b59fdc73c90ea8d7b5b33f8aea6e371ea464f8bc28a5637b313e83bc0e6c5e059c087eb81aae3cf30cc2c21f686184ce2bdc786a2730103eb9bc0681c2bee821e726f388eac62be1ed4a40c38b9968fe554211eee59f72f410c1b4b9556a3bf5118bd95aabff0c20c19a4a1bc67e5
+S = 179296ecacedd93047d4442e8dd5a0de7e2799f45ceaf381cde74f3dfb96d5afaac92bae3df1a572c24757eb2cf91b970cd038278623d6cda864d2db12a763b94198dcb47e6041100ad6308403ad35859d19ff3608dd6dda433c4a30f53dae2d615e612cdb0c0fd4543243b02e873a3ad6a7315b0144a9c1ecd18c446781d7a8cfea621f646a219d6d108b5679520158c3d51287425cc920e65c94eeb01f9b92bb16d167e60906e30e9d2dc8a3fb8d509bfc406994e3d0a39e27d13b3ed5015c61c624e1f3425793c6b0a96a4982997715163ea2ffbcf38680edc6f03a9981d0283053bb3b84061e5c5ec886ff6cbed8041980a49af1ab383f349ea01be6bb0fac45be52a853770e9b0e8f1ddf69a18edbd858eed11c0c8739379de177074aab7c9e20d1783ee7dc46c186eb3966abd35ab08df3574db45b674858b3baddac03fa27d818eac14d3edf5f53852a6e42b052aca9b1ec392d70d53ed10af5b8b5e0df1a6318c558ca47740dee0e5293319a398f01e92743a425a8d4940b65bd16ad266c0db2eb5d53dc3532c98edbad8faf955d65811003a2d887374218bc4504b82b710dc828d838638ff3e8a25cc898c8d210626388132b9e023900d4867350c72ae8c3bd6f0c4d2732294403c1b6b2ef03670e44b2e33e05c5a00299e070a237186b85271a196908609a996cb386d20e285ed3446bd0f03a184aa47998625cc5
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 4a51133aae088367ed396b7e7c5115f017ee32fc10e9cbd2e8947af91c40d9ee41033b0e53b89ab54b46d1a8ef260bb0ee1f7c882c544ff95b81df44cb8229c0831582c490e085c79db650c6c416f0e7a4f4195bb4bc1a88d695116830e35b2c370f4f260c8a2ce50c0f4fa2a329aadb60f6713d4f2a16c78356782df26b587a
+S = 0eb8a7a48915663d4feb5c00c37b1862c248e9305c2644f40b32654b1899e0469554dee6495c6142588d25c7b04d9e498422902307bb8a861ffe02bd3e15eb521241f69afc928325c85508e698dfb5f2ecbdb555829a6c0a1ed7f97a711ade294107101bcae30d469734e7344ab29b03d7bcfb364d219d3d984c1f5915bee9fb6e2255cdcb0e8500bf69d9c8751dacad6e966438eddbe6325141fbdddb4d9c45554e467df872a0dcf5fe9e12b7bf610117bd0662cf2d97c33988c2244283dbd3cf8657c69a94bc48ccb22fff87308eebf175874dca3d5baad98adcfcad551b8f397f76a96f02f398f7e1a5c5d49ad6490d2476b03eca81e806089b5f88c368cc63421f20f54e6b3eff6c020fb3f7a6df34c2592dfa3f45327541ebfdc7f6f37e6ae0609fdd6aae6add86b9a793023bcb0bdcdb051e17ff51ccfde476a87c04a5b2f5ce11e014360dd9547996dffa7c075f7eb4d2d779443ba313af95670a33ecf0db05c7fea3760e53d08707441d7ce6f068d45c746d047ce7fca96106b100d704363bcf82e0b384f789284b8e472581a52004a7632fb6c8d4bce4e325a321d0ed7873aa62b9098c73ba4cd185a5ad2e99850c57167dc75561d630fa9e9b2094c2f327f6f3d097121be3d1444d941002861feddc38ddde941a223d9f525bf5acfe4e5ca39bf39e5f37b5db29bae077d451198f1e0d99fc93185c2810f602cd1d
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA224
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = d9b8ac36d3fe6d7e9c008affd1752d4b928c1f1787dae8da249738972b0b85f67243f69ae60880afd0124fc2577867d6466b8bb410245d82121bc897177a9b8e21d17699670bea189aa1dc6b6c0d2a04538292c08adacf775ad004d2976f5e5c6dcaf5dc5deef4e38215faa1191cc0fc4037fbe4fee484e0841db6edb2d21789
+S = 14ba242af3387b7b0489a0012f787986254b084dfb24cd31d7aa143756886345462f6d98ee33e8477cf0606c60c99b585b52dd301975f7400e73d5cbdf7d91ddc5b7262b615d39f2d0ae48bd5695a61630b082ec78cde6d91dc4b3fd518c413bea61a966b1d5b316cd3878a91d80a64d52f5ef24da2378c43e528b4b912d823bce8987a9b908ac884fba7a03a2129996a60859761d8498e5b9e0c9afd9aaa901c8abfcd80a940ddd9731351deb918cc6177ce0c12cbb27695487e9de6fa23203dad7137e9eadc5259a3c850530c2283e1178c0b2395eedf183c3cf78ea4f3c20b3e80017f669ffc97649f439bd6476ab484b04e0de8e96b596b1994b6a99d732e54886daf9ec82d22e2bccab9ca64db92e1299302eeb031c667aebb0509f6a39e22f2bae56e7cbc06c9a1ab76c16ce0fe5ad92155b330f31830a1df7af51f1178e8aece7bf595152b2530199193eae8c4586af91eb1f713c45b08a87b75d825dee919881ccd9a6448dd2bd0767fadb16415c305825d7db8e01d89ca97821f0293acfb1e85b08d83349f37e99131d3766636d6c7f61afc77c059035cc090e95e987687f3d764264d2c82c1ae4c4766365977365f30b26ba23755dcb6b1545433284a4129dc39625156057f23c44103ba0f02706b16f630ccea0fe204d43d9ef162f0bf17fbf83a10816b66365cfd5b9c4aaa08ec8e1260540e9fdc19fcfd2dd91
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 9b1f5c7d045d72035019a18dac59247ac99cd251dfc74557f2623b6054043ce56b0c7e57b49205b3089e0e571e97ae1452feb784a45cdb9d04781487cdce43ab8f3d170d110030db96df844660a6029073d776669b9cad71b0ffd928195d36e88f18ee46238d3ba48346cb0279706817b48fd8a0cb7002f97f5f53ea419b60c3
+S = 3a9992cd8247ecf8ee650608b4520bbab5fa1774b8381c702930216b0dc6b9040b0dcae567c552ff5870a438d478c805edb56f396e9dfa422464b9559091aa231cc83ba676029936c204e58e473d93a8bb598135463614df6a54dc050f8db86bcfbc942979c3f011b8db0cea0b6bb0695ea1fb8c2f5872e4d89d9ae066b62b062156bba2ccf2be26ee1dce469219f387ec865f16d5b6babde6d0eca2efe1c9a51ec9f1f44a3cefe4eb054d33b80cf945c8bf530b9f8f924952d02fa75c410f3a57dbc2307f03a2cb9455f8a02e1b36b75f0f64087dcae1e639cd360da5d6a7394dcb7c1baeb4b323783cd3fbd207d8faaa5cc3b93867be4d47d934260129f0e51fd1dfb78b3c7c59f02b71be439722ed22654db5c1dc24b83785490ced8d0b97e11f85ee42f95582802446a38d812d59efbc6012a5dadf162aa0979a5de4fb7e4a19b4531c1b11231cb509f3dc05c74d90a1e2a8d9e6168da9fd226d5e53e0cd5ef93fc7ed638287207932f2b1451bab5c4bcabedf244585fa27e1a526cd9c7535768078c2b447cb30b6687d373295d6983ffa31083fd5230eb3574c4b65cb4bce0059d8e77e240d6be41f63fe98e94e76ea9969d8874f92c971a98d184ad6f78c33d5a1051a33b99c2d481ca3c06372f639d78e9601c20f93368ce8a1830d0c5b67aced9f2af6d3e8770321b209e271645e6909e251d31be1156d99f1204ab3
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 82f869cafa1e8bec3d9891bf59cf8f15a0581b41f223afe13ff64efb471a6a4ca45506dc0b1818d6cff83197a6625f05b08b5322b5a7bfe1af5b02388874077624d96ad7a2bedd55df1bcbc23c5d3b14a25bf600c38beccaa276d45b55691394096edfe2487aa41277e8a667a326e9ea7daf4e02a239fe44202f0b8c3661554d
+S = 94d64e8a8f8ff9fb1fc76207b8be1a45f76f09bd0287baec04cc53e08639542dbaeeeaff537b0de30d63ffd961080d3b94708d60b364990c6db0c8ad673e6670f2c476ad7d7a957bf3c46e09fcca93812daf509ed7b88b182ce6f8315ec4787da0b4a0a09f6f48f2cd4a2cb3257abbb1b5c921a0db8c9de8bc64b98f4c347e27d5d063e232e4cfbaae6cb78effedf18ee5f7af1765cb95a3a8db21cf94166de19a0180f7c152f6b25ea2a68703d5d4443c27523baaa08cbedd2e489b0235f2203165f13169e7df9d930fbd7556fd594571a38f4eeb5b428694ac5b9858d233cc2bfe0d21e2fd6f599479024369b7f102b1624ba4160c48028017aae2fa815f7fa439b1545dec9b9e372f7cd8323c8bbf7e182b064deef2b65731d18d2241899f4f573fd9421a4b9a809e9876188db404cb262485761fd9bb315fd69db37601da5805e8e3fa7a64f654a11259c0764b28e53bffcf03d71683ece0fb9571aac451c085c1190353ed1c7a07bc03bd4abd0ce68c6a848a17720dcbb03231e1f505f1a6275d422dd89de55c0d70ada23f5240626c42e64bf33b668c69b6aad7b16534bb10d1aef16ee155df6b0ed2d3768e48171c62838a84c982713aaa5e982370fe10625687a5a960bfb205f85531dc093ba443abf4d22abf519b7db2afc36bae0c10283a551e5aa41c942c9a28fe199522da96b4bc2d640453c6bb495c258578fe
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443031300d060960864801650304020105000420b2b9f428aca658a676034a1382b07d422f560f637c9fd49e258e742e065a852c
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = ee7d5046460f07173172b1dfc3382667b6080522b99da7580a115183475caefa82187ccc938785efb2d6d19a45a31aeff6be80dd092c7e45ec721d5b10106750f84b1f2e902faf03bfd562413fe2d365ad50a6d7dc7175116f300d04a79bdbb7799ea132e4116d9a81f6cc9d5cfb3b110247ded7db727506bad58b45b305f079
+S = 0642e1315d86676ff3f00490d4a2b8285333c7f7a14a152543d85a9f15fb2d54d60519d1896697b1ca9469c382469725455a7124191bc438b3566ed434bf318097e396c049aba9fc85a293ed4187d16bffeef55229cb52b950b504621cf13d683ccd6a0fb53e00d358551a8989c7afc09e34ec90f8286e7413de3decad04496b5a749a081c0e82ff71f6838780808270d72265e9abcf87f0e1f4439f0f7b3ab95729d4041a502573f94aa8fb1989dde4c2287335818f0fd03a72b4e6811249f665b0d05acff32069d80f570782f568bc851c434d82cc94fa168b6f2619a57a97284789bc41d9bbb29749bbbc3470c774079af80eba8287a2d53f4e14df1e619cc8b5e7709d5c54cd4b0cdcc8693c3d04b460c382531e749638736226a9ac2605f82eca3e3df3dae4f2e7cc70e0d39fd2772f193a4df10a25b58bfbc5497a0ee98e8f60cccedb1152741e52e53bbf3ec1a23bfa44b73753c60d69c1615c58739f2f093fbfd6c9ab25799cdd9e8b65bcac94af0ebab3f66780c3fdb486cb20427db12a97fd0257f1b7c956733304c4d30e3faa78c27bba260d697be1ef36eaae6c87d49f36112d7964ed7683fa47597fe58b212f19f4cc1d88805cad324fdf4ee05687421e827266d452a851401cc02c4af7a61fb1bd40f772bc1cca4e5955710f2e9ea23bec04ed7e3054fe8f1170c70935ee22384a43e82e1e855be59d428f8f
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 27331a2203df81efd7f4d19278bcbd4050c32f8fb6df3a93786e5147b6dfb62ff774343c764511f0bd893fc27511d2c47d15b7833933a22f2db548fcca13cfc787b882fd3409cab98ba4592c09e5a942fcafa582dc69a637de46a0cdc7ca9e7dfe8a6b2de63392916acd8997da412a02f519625447882df2b5aac283560c0a99
+S = 4bd55acc43b26d2e69cdee990682e40580642fcaa9c0057c2f3c6e3cff14234f8e7304ef16cd79ef50c6e52ea8b02a46915ec21371556d217da4f3820eff0dfbc1a3dfe8bb43756e2e829d4bb240742e604e1d6b1e3dcaf69f346839e0351cad7b10c165f34603864c47e6a01420e677a421352f4a20a18814b1fc0db029825ba182732ae1480cb1e18fd1ecfc6d0fb6b6bb32944580aad72dc7e9f0f9dd41c114f8a5e77a1a07da0b51ea830a5877ba964460d45ac122829976d459dd7e49b74130c201d413ac78525f75463f69bd2c9da63c848be84a240368b7dc004e4c26273e5ee4a0bbe2903bb59cc2200fafd222fa59a5cbce12ce1a375ad512284043aa4d44abf3846d9d21b3a27c28b03d5cac655f91fd17a9d0a15f450db44a09aee6deb337ff3837bd85045c2f716ea147f098ec2560655492427291a1619404c77985c860643e85e01a767a8367ea387f930686becd9cf51e6da3a5183ac306d30b42d7b41646355f77192939af92a248d9243144d6ed0c440c60e656d535d5e656d8d22df272daeb01336ed4f57f5dee8f8514d7a100e996ce32d06c1bdcfa8d490a53d0f4329052491e5f3173f0430f07f18869f866f8403a389b2be6b68efb44dcad6537a2e305500acda845b5f50e91433ad84a094c12c0a38682bdc3a54fd3f6b322cc72fbd2ec805748f7e82ee3e5fc4603140e3b0813cf81e1861fb2e4
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = c8ef4787dbd28656118a8cf26f182c77f48ffab67b6b522be3239c306c02cf6f6432349d041a6d6695eab5a3d67369d3a23dc8c9ced3f7a2516247faa782bb607754c50673cd51bd7f5104211684c611ea5d7e63cb7c1cd5cabddd469e0dca26477c832bf1943a451ae902d5f7f24a1a1417a4eb3c0bccac985ce57b1a4905aa
+S = 578c8c3166a0199da16eb3f93eebe5d2bfc3ee668432bcd26d8c87ab349137f5392f60b66578eaaf47c3fc7ed0101ee650b51fd522f8d06474345eaa73e253f8b1c133a9a874c6234381ba4b8dc0494d1ff5d65167b0c46adb12538cfbc75ce1042e4d69cfaa4ef5083c08f91f03b295e0433597e0aea94dc596fd015b4770db71592b9f41e3b587313148a4a2784f1bde2755034bd99b15ae982e0e4ad4c9dc8f8d8ab06d692251520c813b540f5b514f88827ab94b879cf61bfbadff5277239079b90d023826f2a8f330c37bb3279d0ebf0659196cedbd91a347e8e0235a009d7f39fdad4faaffca75f6343fea2ec8c588776b64ec1371c90046ba5b6bb148a75c7748e11649442a77ed80e76a23b1c761b9e3636e3147ac6fe408fede1f4c7c7b8ca651abbbbd20d131218e2e43bcd2252b1b180678d9196c6067a0473c8c73f0610973807746b44c2bde619a5e4f4cb3371e260c47eaf31e935c025b523c39b659098369fff0215e17edda2985247c90b3d84676110e1344d538aa34dced5f97c71921406adca7bc1ec54ca66c43b7321497a71310f70184aa3691451f5207f455ad947e33c9f22f7a96fdc970c325a286848413fb092271a295bc0de317c0b76a2617fb0fdf2c792bcce16b9c3f5c4f03dddd7ca4b1adaa6f4dee058b1b3a2326086e5140ad8618c0c7517b148f1054b897548f881961d54bcea391f7a8
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d06096086480165030402010500042077cab6a7538318a9ab5fb2c9399130c8fdd3064629374b4a49b2b88bee0e6463efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA256
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 5d5e9a1c2ab1b7c859c7cdbb21caf3fe77ace0bfdfb05af6832df249828fef2c8a9e884ca903562e60070813fa9f59201ba63fbb9c6965389668dcb5bd5b0e42f074f3460ee4871e0aa07b0642652a3d0cf9d06492b5f627e14031203c9d0cf8b66843d0005c32df7f198c5ca124509e7230f9826a9cf60d893c5952a75cd396
+S = 5b460ece8562655899aa4ffa98650e7043766b0b2735662ceaf6958df776efbb60c92330790a57cc26093db03f6dd9a02f0046de5f71397d496ffe41d70f4a0b2e98c0c080dbb546726cc4808e70cdb31d84c23c021c45b617c7778d102bad94ba0f98980211eff7ccdd43ea61c17d08f9e319bf6b36b56ca3dcd8b12a240d81cee2b7a7eb234dc822f610e2bc712eb1d9562d826f8fa902107487949fba4538ddbf5d41d161c55fb3fedd6d2c6f90ec177d672e136f1352f4d07d5c21f0173928292e310fbf40ea6d9e974ee5db68501069310b6255e0a541bcb335934e15f6e504807884cd46c91efa9e224f8402fcaef986da5f159a35a40ea221afcb9e00aaf968cacb7d720c2aa1c5025cbd2ae9e3857e857e9bb82981e43f3f197c1286ca0819a7caff78e3621807f2682fa10a49e7091419d99ff0f42ccd22c5b455ca8214117aaad92e46cfd8598dbb533b38d8a4d5f8cafe6caab99468a7bf540f5a7f15414c76b5b404a6cb855af8ad7d62c60959e489a40ded9898a3ee04fdd3de2f8ef95a207b226daa9e4ddcc688e7636fbaeddafc0282f5924f7ffca4f9cdd8115bb17c36ac2b8804c3afaccc1ed4057b97b59d01705cbeea65cac20c6623cdd66cccede7f1db9d98d567e5c48116159b8113f8247a879e0990c2a3ac8c817bf6c98902f8b497621a53ddbccb07d01b7f8694a45ee68d2d04a33cb3535db2e6
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 0a5d9e0c5ffd0d0eab672509388aa606fb5063e26d23aef59ab011f274eb3f0e6e5349654677159922b90dbcdf521470a696be4cc079c082ab53a5bf6de0c353288b6e92efec6b7ad88fa79652f72921b9e2466f28cf14898fbe2118053764845f8d735c0164f7f9f4715d5e3981cf635dbd63134e2c92526d79ebc3e4f708e8
+S = 31af3922e01de9d2ad34e11b89c1ec21ad76c2913375137206c779459c2db5fa9f180c1a061393f1106c7bd7c0c19e316f37f47f462e1fd870d05332ebaa582579f15e48729e5f8380c947f563244d08aa2104570334c60fa0a01a9f0bf9aae07e2e7c3e5de6acc71f8b3aabb9fe6036674d8eefee4fe7c0e5d3d9323e3fa92931c1a19689e53f4fa53381c4b73f8d91577ca7ce8128b88e8340b63f2e89a4618138c68ee53fb05ca95c94ecfc2526eebc9a38930c12c6f4416db316c507dbee0fe64a3bc66041aaf95f67d9a0294d97b4a4579e0f946fbf7309f042307fd3611f5ff2aab4a738410b62327d2b57cbfd05c5af3e6d61c794732fdf160e61b8bc6a4d3511668d2340bf6d2d1d46bd960e9be045d83bb71a93f1d9f72c67d8e318dc9c78da55758b660e2b1feb7ced2e8ff0a4a29e5febcb40078c92b8019db63551ab866959732aeba71a94df7c35d753e5a831da820d45f09a530176ed964387dda6e7e047302428583c16ace2f4a90f86539c756c0b7baf80a1475851920107fb9f742db3086067fa0c8a6a326f14ba69f8dee961e5cd7407dd5e6d74e81730492d03f825cceb96f2261f2d6b3bb48df1ccc07b9830df23aa26aac452d99d61bab38735b9daae68caa8a36ac7b57e01d181e6ad3321851bf42cfe627c0e2526af37abe7a8f454d754adbd24fccae6778547651d281354e2b167a21cb2e58a86
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = c265cc1668d494b6dbbf477f187eed2a862a49392b00b180200a1de342fc7d612b5c505261e572eccc2e350c6e87b4344e2364cfb57decbd9df4370b67b8c702ccea4c6416ff75f2906606313b6a2b6ec2590b00b0e6a1cde1ccc71036b494598d59e8d5f1ea45cf0db0e177e7f0f9e2cb136753840477b9d3daf77819b78d6c
+S = 7b6e5c6672b76a49b637135878e9738da6b1ad1710a1f8c557c5de7c3a5364d4927f3497d6b7daedb931a65e3433dbfde8791af39c97e90437155a3eb3fc96c37d2b0a51126faee5706b0b73c63413f9082d6f0a3d2ad7fcc69e935c016a4abbb2295135bcef8c078e11e262c0c1038f4311926823cb1b148dd8e63942a927e806a84260e51341ff99eb02fa053dc9258b4113da1d76d0734f81234a51a196139171a90c60c9a6f6baadd3e3b99769bd1890984b3e434f94e9f27c7086d86ee86d45ddbd7130bde845b6c47b6dca29edcd6f7898a42e499555700683732feb4c2e200c0fb1e11c0f314682ead943aca08e276eacc1d67e02018690d159a7d50561bec7087c5e21b32bcf2b27c0245f410df9c137696f014befa4a0c13fe7302b44393bfe6e3747cd88ec2dff0c639bbca4e7ecb77f7989a35c2acdb6a9dbb70092a9b7f4f4c8c8d9f7286d9666b24393c95e2cc256c03645944fc7b194a73be5a6acca491c0a98e551aadf5b002a1c42d57149f6788697eda81d1735a85442b6b313ba798c92ec0464a4f02ec3cd5059694428e0961c93e75155d1e5f965e5956a82d7f9ebc51fae9ed151710768ff1c172ae2b68c81da2190575a35cbb5f9eb52f56ba5f838d05d40c35b9fe901a75d5d96e09b85841d68d055bca786514fc6249b136a22870379dbd54576a91b646406ed12445521b67c694e94626ed15f09
+SaltVal = 00
+EM with hash moved = 0001ffffffffff003041300d060960864801650304020205000430c0d206b5a6126ec9a86519315cb38f2484d00f36f2065d3a0dfe6f34657ad926ff281b90d8187ae2c2eb45c68643c352efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = f1fb8e6cfdfc5dd3931e8fb5c92b974650224e935787f170acfe69b22418d09f3e6d30a303eb8e45306d2758978ff976c3c185aadb9bd46dc871b8d49a2654072845def5f74da4465e4d4d91e7b162d0f75c0d11b2f7206e1988583e7546e48df9ac21caa3cca8c063e68ac87f39da3c36196c2ea442dd5ae56cd35a7d1f8619
+S = 2c0ce9b108db78aebb905e421bd0a993b38d9e6b66bba9cf5a9ad72fea11f0ea2a8eec30e7947fbd552c63535f2097e4d6ccf07024e833967a119abb869327d880ca2c21c3f32dd559eb8fb6090107832aa884eea6c9284231a6869013cb0654b3cf17cc87b39a9b7612e2c91f77ccbc1736d1c7e5816694632fed14bb764c4c4f5f80193b6fb9247026a3e754805f00cb8a73b62f01b6ca9206890aa3008e63a2ca87a0eb54affe1e94f2a676060921620ef8bfc8563abfc9006b8ed0f7c71cb8a987daa6d96c0b819e4d1cf279417998e8d9f7f4334186923a10d3ea888e0b8d8699494c9e5a0468345f1a93a79b436b864a4f84c74f77d95ac7095156d96d4b83000177cc33c8ff9f555bf5afd2968708eee4b10a397ab76c3ff22766caf8d3836b5d5fa7a580bceb6245063bfa74fa9d79cf2c61b8ab92a92ffd93eabeae820ddd5f4c94301bd7210b18142126267a1b2ef3f8725110ad570a7d46ef5a18fd32b031ebf23d0c4f56e134f76b667217d486845f93e965bca006934ef68d5e11f8edb1adcffaaa51b5b0f42959473c53348709ffea3963436dd7794aadee13aa24e1872152b9bbd031e71700a8924556b703c7be70d33e523d9ddddacf0641756468872c7ad17b71208c78fa993561d54aa6255b6abc5d1b9ea7c58f28554a76acc9f662e186a1aff26e6f7ce8c9ac20fb64cadfec72a08ece04b51bda01a7
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 879645d6b8014a368de5b3f59c0f6d61d05150fd6978461c447db0af5d00055c92f1bcd0aa916d55959933a7f5b85403de432482da2926a5312575316737623d05545f899d5d1c11084eefe2f2b8792d9971879ad18936de4c815b9018b821386926f4aa994c9e926d6bb04f9af52405874140ed5582bef01dfa2975786b8a77
+S = 2287114cfb12bbdf370c453bb39e68bea8c24afa1db85239b54f7ced68798dce71ccc3a283859cb67717b7d0299f28238cf05c9016e867203afc345498a98cc933165d1d2103263f0556ad6b89a408227b3d68909f1c31460f818da5a389033004e5d89909661995a6c98fa3a59a56869cefe67d06a7e5580e288a1d69eeffb1aed49e77adfa674123690d42f83411d807ee7fd5a2b21c055ebf9d393733c1fe96d9a9678814fbed5cf5478a54edb8e432524d0c05022a5b477c4fe901ae8b4a8e8d00b1519075fe5e160eb5b1c090a7b1deb970c7f900dd47c47bebcb3fb5334be683dadaf023660d0d82ac0de747f0982cc31428ebcabb03ab4eb46750331fa88db48c15b40dd18a83dce93e7e769db6dd32cb99a78243233d509528b03825ddd5eaf2f29b68396e23293607e8bd5455c23843f63304d5d3865943434b61f471e2b3464f37fadd3d29dd104b36c9f6f859f4d84446364fb56af34e9eb15882519b072b890d682b254d6461f997e056b42452a2346ac6f0653845d456b20c3a273a7d421295ff91871fb525c7274471ecdfa93c9358067dd4911a3010b629d0c2b3a2db23af2a4510d6230522b170b61e804ebf561c7ecf45c5b741c37141ee407809901d557e2c8f88e7a719f2d3b5952928722e96311b9a1ba5106cd5ae9d8d101d583d321fd42c68cf4c28d944ab9433153831e3884556d485c927970f25
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 92b5088f66c761117eefe5d57d490b0a2d8f735adaed7065f910c46f0e81aa55cc311ac67d5548afa4736ef7e1bdcb6d169febffc8942a2cc83d74bc12b44eaef51e1a72747f9658edd3a749f85a55b5923316cc7b2c4ff1dcd9186b2de3405e56a390fa14ef54f39f3418318ac5b0c8ea737b2aba5ee89c7e0b38e627b6864f
+S = 50758bef01ca5623082d4fb6888e9c27598bdefd63abd5168c8a122d4bc26e45d50736136f9f28848b082f18ae69cc2c3cba98f3458cbe71167a6629ea604a606b7a10fba68edd1576367ef0551b1c0dac9ab830ba41d7c9825ddab0a4cf01c62669d3c7f434e18c6bba0c6b931f6317f66f0aa6694441bbb9cfb74220920d9d861a857cd984c0e35666eded9d6d67fead62231f2cef40fe4252d02aaa3b12418d26cb646128fa69e13c57f90a85a7606859f84da62feace94bfb607cbb8fce4c23006b1a3f0aa6724072ade5c1cc2c664556edb9d40ff63d0de44b35a68e81aea98e98d52883c4fe41cca6f1f09398251f28d30165f34b74b008af8742b93c8fb7586cef90efa60e0542f3f5f85dbee12b3008c834a13c587dbda2e570dd12149390fb7e8788b46502046e0e158c3aede9c789895af2508663d7d1b9ede251321800db59575bd7971bb9a93a2c0ad2ec377f0268e7b6eb404c0cc02055d0e69726176f39b8826b1bcf8f4df7a7ede44a5ebe2d862825d6b1c11e9a30ab838789bee11344aa1d88e8495792c68344fa889ee8c2dfa418b5fcd18ba7cce65018fb6ea8d00dee814084eac349f5a233f34b2921cc0f09b5f6b6aa4cdaf90196f14ea66dcc9ab1ccc4acc1ca2d097bff923252db6d19db50e877f6848e3a14dc8d799fd8a8722aa6e98b5b4e53225af9d2c40811c6967e525db1993ed1539fcecde
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443041300d060960864801650304020205000430d6b9bb354aa8acf8326afd721b8bbb21603ef5d2f897c52cc0f27f9169f5bb894168a77ee4a65079fd68e9b38a7a4ea9
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA384
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 9a5592fd0be381aad74258865cab802a5f161df848a2e3a38e382af2706b45c0e6a31048d77bc99f8c672182659a9252ca27f25d6566495f8e99e04907cf9a40ea0987e9df9cb7e492d64c9665e4d32c62f3d5dc7396a86ed5688bfccaf2f3f68ecf1f688d0df280d3d7024bc451edbf0dc4ecfedafbaad94aed56931f9cf6e8
+S = 6b95909cfb0edba3177083097f74edac27b652bfd73575efac3db0971290bd7718b5a5491724c095a25c1a75b67a24a9e7caea4e2319637abe40efc0c5ce640a879978aac6ec898a4cce02b87cffb59f0c27c1c01759d7f698adf77003e033e70895e64a1f50f8cc471f61cb8e4c37a6a32e0875551b558314442fd7880c1fc74046b960f6fb4938ca6a7b1fc709cb046cb51c5fcf32c5d8e63324c88cd3ba6ff43406688771d1fd5ace55ccd8c90a96f403461f65c1cafd3068c4be660ccd740f34edcc1b4c57ee0e5ea5a3c2b9d76e583a9d1c70f480f508d589e72dfb0e5a6355bd70a2f90bddc1847d582d426f37b1060e475bfc62ca3133f4431407b948cbbf8ef4ec6488d773c5a840ffe2bf2cdd8a9aa753d0e66733daa5837f26eee99be7ac230fe0437898b6f9cf8e92419f0ee112d0475dfed75f8a8dfa4fe2f1e7d54da8fed8bd883f7326890f74a61beb22ad9822536bd3780f8a18573d16376f4f393e8e2305decfea889933b92d673569b4038d49547cde3c11e4f1331ded794c6fdb266c02048ce0be47b829e9be709ceaea89c3acfb12741332d147d8fe981b146955a29186f1b44f69ea276e78448d5752117eae565cfa54e6dda92387f330542dd30bb9426e1965a76a5a438f55ce22d252fd8e62df04c4e8c7a719385d4d56f37194f7e03368d17fe8165ed176d636b3b55fb99c483d707d160543561a
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = e0e52ff4aaaab424199c5cf2a172d1ebe64f7b6e2096fe19c400048161ec3c26c7f6a3a66fca0230173bb73cad8fb9796e1dd7074f1b40e79cb148b0df516983034b8840b99c7afa1b07c7a98f68ae1fef44693ee7a4b2679e2485359847286cdb0d692c50c8276b6d2b13a211a4b8c5afecb979afdc5a821182427a547480c9
+S = 8c61782fa17abd9424bd4df6333f775a1a36cb913fc3324d4a860c4619ab778ec699e88cbf7d55d8b9e7c9a4bf760ff1238c1b65f3d3afb50702c844706e855187ca2fbc92c18f5ac9558b8b719f7e985d791caf719721c66673026c393fd6fe4aaad8829188e5978ed401256ab8ece9d6713b55a0b8cce1c33b9dc333ed48d83bbbab4290471866d1d4d3e239daa5f315e18a19f78d7679ea1ba028032dfbca40ab0ac436f948a129c7d182911d0452548755a90dffa2294a4089c2a46352b1e76e06c203e230a0229989ddab4171deeef125af7ad0be3f28dd2d3cdaf25ef500d8d7134546bc79806ad7bc8dbdfd882f6924148b2480cffdd9d4ef0235385c76687fe669822ae14238736c4e8fa48d494ea578a6a940f07be7284274dbe9aabba9b6077d253eeaecd483f60763f8baee3d5e27a7c820c103160df87f875b10ffad7d810283fe118fd040b0e64b8b007aaa049a5ea739f85ad8245e0223f3bb3c66904bb89bb58eed61324ceb4b49b951de42d1ffff7ed9905050d05c73f34946562d5d39acf768f7be5292f20448bc5b61795fe077631587abc5465e67fff8118dbefda942bdbbe673eab46142f047d0359f112f64ba92eb54ee45b349bcb3befb89e31080d48303c90acafa4aa09466348b50f2923d29c1f9bf34dad7b3246653c7fd20f480b33ef3d9e116ddda73b7791f2fc5fc4c31bcac2bde5b79691f
+SaltVal = 00
+Result = P
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 2fd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33fa217c9b26e8453e4a6b2
+S = 560a204f8a24adc61ac4d3c8de48304d9c59f6faf1bf1059bf1edb7e786ad81d95d6e17acfc30d84a151ff5496507da3094b7464839443d5530e22d6316076fadb5ffa013319230b14115e0905a997f4019dad2abde8d415a2b040bc6413c172a620a878d3695f70ffceb14fbeeb4538bf3c9b905e5907cba8ed8fc4a6ef9eeb863c99251abfaa9c483198618f2858a0c2d04a3f7e1e51128c9309303e01182cbfa20ea398c02354247fb30d32e977e6ea2dcc97be8921149257d13e31dde63b4992b167dd87f53116114a6344a3913ee313b4361d9258a2b10e9cefb19d0455466574bd58c0f284f99362737d0ad83d3ed0d587084f4e677a6748d68c1e3fee364600905873bb10de67b02e0aca45273ddb2f667aa22e885231b2bede0b541b79d2adf5e251be56e43b2577bba5244838471ed6899871016372771f88ebde49a776bb11697f15e50d490be4e52f95868f01bbd8ca549a60c50f1e99ddfe399f76fea48567e6abc0a845ddac6e963964624e38e1fb56565f99f3cdd7ddb7aebc3c53c7d82c6e3eeb058d128b4bacaca5f5fc8b037818d34c732fd15aeb70b0d688a233b5f91b65ff1f68cfa6f3a55b144840a9979996dfcfdf84cd9b02d385a842b27121cbe645155521e2c53ba3f1747af5609950b0cc808f33402dbb94fd1128fe9b309850b9ef11e82ec0498d595ff6436aab76a4df49047d76e5342c14b1
+SaltVal = 00
+Result = F (1 - Message changed)
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 6ed981437f350723c4f1677f7bacdb78d12a22a19b3ed30646edf16d11d0bfdb79bad65af59b74fae4a41716c4ac4bd8a4d3c0ffdc659fe0fb011eab01fa53f0cffd4562dbf449da282b8c9f76b1ece4b6020c92c0e2a748488c24a00e0c6bb556eaf8e298082dcc78cdeda2f88366a3edfe2ee1b07f924515d82bd4a1d0b230
+S = 4684f8bc41880feaebaf54fc8cbb1d85c378db4bb916a7e162fa6683667b2f6df1e41e722f57e027486dd2c89ec035e2fe88ec082bbc105422b9116362bb00fac7f687297a858a08bea678d8489ce7cc27133c4f0acba0c7aee1daa55938ba2fc8957e6dca7493c0f054cc8a61d96b1d2689b1af69b491f58aeb6b3011827ad0d60bf1385402d4c7e7dac0f6f1259e7069a788816cce8db301639007ed1224bbdcbef9447df741cdb6a1f03796398372eb86ed8c995d281326a834688010becd7c737096de2573eb210035f14b937cf614cab6d1717711685e029b7b23d922bf2d6d63e354af5cf1b8609d021196e04a4e1baab203b1adce2b9c4bdf5a9a989157d2832867abc5173e5944ff070c9f7b06a14373fac3bfd76a73129e4cd0420c4696da9ef6f672f4cc9973434bcd2f0e351fe4509138d20a55bf73e42365da8d7ba3dd74b86055a785d346546de0f9837ecbcf52d6658e16e657b20428a8003a9b31d9f69e8206da1068fea98ea282a8731d96fe5e5be7d0b68c9eaf16090eea1f424e4cc5a509f8d6efb97f846d8ff1bd739288deeeecee6d0122eff6efbba9541ee1b2387f2092022df8584521d556bdc7ff9c8914d35a7b44075382fa3f03a3d4ec1ad11539cdf3b92eb37da08949c7ddbc2108e228c4548f41224b4da41098ae67a048be0fd22254a49186360bd0cea7877621130af6b8abfb490a108ab0
+SaltVal = 00
+Result = F (2 - Public Key e changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 3a33da20cfb3e3ac722e7df7865330b8f62a73d9119a1f21992e240f16197b0970775cb6bdd5b0a858f4c93e33ca51c86eca80ed2865924a95d1795c5009cfa0f3150ef8e68b03517456808324b6527846887291ccc880455b546c0ca2f2777beb955ab0efdcc4f0efdc0a8f001f1a10a7ecb28ea5c9cf5b143f67e6b3dd5ae2
+S = 2fd9e8beeb55cf3640f615951e25b1731e1c51b4a1a2f251ff2761c3de6393c00f1ee2876e103a38c3149eafb804efa687b953eaf86b270d6cef192869aacc206f2018067df43db0ad8de6687ecd0535ed299180521066553ae2e6ed21604193eac012986767e48aea294fa3769482bcd2c167723707284dbcc7849d8320220319f7087baae33e7d05cab1e1430d3b2ba0e9ec5c5620f097c13b5a5a7c286ec9061f1963d27aafd79e2a217da1cb99389a5335ceb7690db3ce5cac022a542c14be25cb3e090400653a46863f443bd40807c546916b8090098fc5416744aa8d167bbcd48d718f5fee47339ec5446bbcb53ff6270f761e57589c399b558a24da5a5b3121a4a296e1ee1e01395f20b967c6cfaf2dd92e6e9fbc7c866b910570808e8dc87b66a8d9518dd9829f71f6a5e7e544e86551d907fcf2da2f4707e19586c19598a063ec1bfb252d91449f22ca90f2f88bbc6266ede3c19912a2481f70795a0a6ab6c1644a9458f9dce7a6459587135f5e3f20944a00d0874ff3b748a12a81e54a33da1a65df5dd932dbd979c79116e7d1138d35abf18b2a82c364490975c118c194c102a7c0eae6c629ec8043f9c55b63e55eacb3b352250ef5fa489ace55ec6b0771711aefd26f35483dacabe89fd15e248f669b5b2c343ba9de80b523432b9a0e4b05486c0132c4e1608f49efd481aed7b6da2ddd78fd5bafefcef2f074
+SaltVal = 00
+EM with trailer wrong =0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff443051300d060960864801650304020305000440ece68078ae14353fad83f9da0bc52f954e4f83bdc06abda384df386e15c66759f7a78859e7627c41d5c146cb5f8a46a147f1bb3ce2fbccd6d7efaa3d098c0a64
+Result = F (5 - Format of the EM is incorrect - 00 on end of pad removed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 244581a2b06130d1af01b83ab281dc252d97481cd92819575660a0781501637975fb65e22c3ea83fe9ccefd13812c884a578ca2124371cc5b06a37923369eca4a652a84679e8f76635a1474760faef76a10e6fff2467f9e0401431be57fb32d7fe71d1385e082530daa84704f3e256e46880be1ea161ba924d8418664b623dfb
+S = 45b532bc216a9e6c0b58ef1e500e0cfc11cb85614faa4301e5c373acbb46f1fa655975b8fe4d50098f5b1ffff7e45db3e339b27b2d6d3349fa952922b876dd333c862bacf6cf4d3b1b98fca4adc2a4674b0397326ebad63a553f97cbf763d5549e982b999eaa77dfa074311d236936056a2f097385136ea5d82f76190e4a896bd5c2ef3580eb98340b136dae2215c3ec324ad44fa1920213fc6985faa58fab2a5ab4f1c268dc1489c4f257e54c573247a6e32640780f7345dcd7c371de12696a2fff5d94ab9677914d3d21fd0b436405b8122f410a3374ed67c8b414120a1c50c18b6a8acaff5bb68b2ced8036d30045378402e4cd193cfab277e9808045b30c65f947f39c4b3b25af8130a46d03fef6ab01c8d3a5807ff6a96628523fcd8447f24d11cbad36b5553f5d4c8051739a700d6113d48e3c28bee871fc00c46b013e887ba957ab45911f056d4b98c00b4e6b5b02b1d674918b90b40ca688e096ad0705d6f72e4999b0cbe9ed94cb297df6872e02fbd3ed2a8be758d4e6af7fa416b14d6785852b2a06d001e1b10e9829e3c6ad27bb2f1ce05104115decac07ff9c4e3cbb0bc0d264e9f27e9dcb48a9d8ce44b5e6cb37defc81e282071eb0ea06285c5afed12fa5b509a54449dbcd19431ad4522348ab0aed336c351709d3aa717d1e453362bc65d041af2fa7c1328231420741b433373e78d98f23940d6e59c132e7
+SaltVal = 00
+Result = F (3 - Signature changed )
+
+SHAAlg = SHA512
+e = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011
+d = 09d77b3b07c31dacabcdf1e8078a1321cb08f1765488e71b320c0bb56cfc04868a0edf060a6a6f90691164844852546dff634167aa1b0fe81d69fba8fcebcdfbee9e781425b29af7c5df6156d71b1264b592d53efa8a7bfd4a0b2fc0ac1863904241d09ea376ecffdcf36cfac560c74b210c1c1886d4a6dfc94959f5190e8ea9082d85e7e8fd58bd374db170f86362ed0b4c2a2084ce93ba924a95e905b52e1a9c2215cc3d5d8de7d76a718080c3a15e71ddf60af46bd9ba62557a00e9ced85ba8f0751dad3f4e212957265c67de3eea774d7f7514d40a0814880b724bc1ed43de7e7f34334ab19f9e50dd5fac9403c6d14b0ea9e1663e63510c96419c10c134de0eb4ecf88918f782e272ececca42a6c04898a0c738eceea3319e81c0e6fb4236fdaaa191b196a7e8fc39e35a88d844b2c2f0929f029e49b03f1b65804ced3594c1304fe2ae987ab4d24a7faed4da097d58c94125884d095b59d26f2fd207e4dca58c54c0a74115d2f635a97e86e484ea8fe5a25a0dfb787fcefbe53f4dcc299ed23802b79ae2cd433227128eed0bd640bb5f51c93707379fd715c7a39b69c559fb8ff6d43eadb2eae2034d93c0c7f39b5e50044aa201d4d0c3036e4004201d558c4b87e31bfbd10654032808d9133200f8ca8e8206ea26fe2a3ef27005d2b245bb91c528fbe9a45687e94aaae83cbe25b452b3c26bc17c3efda7818f24201d
+Msg = 24c8f1e99508bd234cf1161e94b439ac41e6392994d4ff685e178fee68688e5e13b501353c7458b76237ab2a0b80434163d75cdb271b29eec11619bdb55359523b349a282d3f142824b9cbd6df7611cde4ef4c696995f9c37465f1e242bdeb2fe66e432a3212fa5cdaa0fd8cd73daa360a55903922eb76d0bf2d9fc3d74c4ddf
+S = 3941bb2afeacc1962b51ffecb000ed9406ba6e0935006203eac5aab1e35b980e6b3bbacf6d79f249e2c0fcd4259298d659870fbfa7e5c78d0e72aec15768e9e9d7353369ef2c91240645dfe40d85f68026bc4aff204798ad20cdf05a66640f6885ab633597636cd5af965ef1d2bdcc5dd0922f23e150ba67cdf148421d6ed43349b2ab426af2c9609eda45b980c842c2817513f8d0ec7c1b404fe07a7269088e359948fa05a6d63d3002f88ccd3167dc30242a42a07b17940a4f5763013800fefced30d42daef920e15d167e6bef092d440be42624e6f855ab7842a8871140dc17458f479933e082f1794a4c56cb338d31ca4f5bc6983dc2ec124e6785b16a0530b4c7e33488da83a184aff5448277a61c32cf6a8a4995a939552e0cad8d37da113b7806510577af56f9abfc7a37c566405be6d0b3271d8dd9071a0e83c51467f2fd3d22c805bc9ea025d1b1033a99235acb145729df2b6dcd761196c74b02f8aec2b53d19c20be6b3f7e46c21690737c675d46d240d6774278c0dc7db0a817b570cd493530d2acc0685bb1d51a81992ba45a3acbb690467fcd2524deef1b2efd643cac753d86a760c9428427a7b5cfe2624efdcca0f4c2c02ae67c3e3df01c4a19c3172377b425834c1c376366eab600693f63ece2d6ff94412f768a9dba4d202d70a9324f76b2f58295015164213c71d3bae7b90edd800ada1d972353f320c
+SaltVal = 00
+EM with hash moved = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003051300d060960864801650304020305000440f8b77aee7f4480f3de4575717e774c7735f9d46cfbc3706fcc2cbfed078b75fa59223ba0cda570d5bdf5ba1bd9d087f37e36b22b65552b85cfcc01a7b30c7f78efefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefef
+Result = F (4 - Format of the EM is incorrect - hash moved to left )
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/SignatureChecker.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/SignatureChecker.test.js
new file mode 100644
index 000000000..e6a08491a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/SignatureChecker.test.js
@@ -0,0 +1,61 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const TEST_MESSAGE = ethers.id('OpenZeppelin');
+const TEST_MESSAGE_HASH = ethers.hashMessage(TEST_MESSAGE);
+
+const WRONG_MESSAGE = ethers.id('Nope');
+const WRONG_MESSAGE_HASH = ethers.hashMessage(WRONG_MESSAGE);
+
+async function fixture() {
+ const [signer, other] = await ethers.getSigners();
+ const mock = await ethers.deployContract('$SignatureChecker');
+ const wallet = await ethers.deployContract('ERC1271WalletMock', [signer]);
+ const malicious = await ethers.deployContract('ERC1271MaliciousMock');
+ const signature = await signer.signMessage(TEST_MESSAGE);
+
+ return { signer, other, mock, wallet, malicious, signature };
+}
+
+describe('SignatureChecker (ERC1271)', function () {
+ before('deploying', async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('EOA account', function () {
+ it('with matching signer and signature', async function () {
+ expect(await this.mock.$isValidSignatureNow(this.signer, TEST_MESSAGE_HASH, this.signature)).to.be.true;
+ });
+
+ it('with invalid signer', async function () {
+ expect(await this.mock.$isValidSignatureNow(this.other, TEST_MESSAGE_HASH, this.signature)).to.be.false;
+ });
+
+ it('with invalid signature', async function () {
+ expect(await this.mock.$isValidSignatureNow(this.signer, WRONG_MESSAGE_HASH, this.signature)).to.be.false;
+ });
+ });
+
+ describe('ERC1271 wallet', function () {
+ for (const fn of ['isValidERC1271SignatureNow', 'isValidSignatureNow']) {
+ describe(fn, function () {
+ it('with matching signer and signature', async function () {
+ expect(await this.mock.getFunction(`$${fn}`)(this.wallet, TEST_MESSAGE_HASH, this.signature)).to.be.true;
+ });
+
+ it('with invalid signer', async function () {
+ expect(await this.mock.getFunction(`$${fn}`)(this.mock, TEST_MESSAGE_HASH, this.signature)).to.be.false;
+ });
+
+ it('with invalid signature', async function () {
+ expect(await this.mock.getFunction(`$${fn}`)(this.wallet, WRONG_MESSAGE_HASH, this.signature)).to.be.false;
+ });
+
+ it('with malicious wallet', async function () {
+ expect(await this.mock.getFunction(`$${fn}`)(this.malicious, TEST_MESSAGE_HASH, this.signature)).to.be.false;
+ });
+ });
+ }
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/ecdsa_secp256r1_sha256_p1363_test.json b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/ecdsa_secp256r1_sha256_p1363_test.json
new file mode 100644
index 000000000..9cd94cf8b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/cryptography/ecdsa_secp256r1_sha256_p1363_test.json
@@ -0,0 +1,3719 @@
+{
+ "algorithm" : "ECDSA",
+ "generatorVersion" : "0.8r12",
+ "numberOfTests" : 219,
+ "header" : [
+ "Test vectors of type EcdsaVerify are meant for the verification",
+ "of IEEE P1363 encoded ECDSA signatures."
+ ],
+ "notes" : {
+ "EdgeCase" : "Edge case values such as r=1 and s=0 can lead to forgeries if the ECDSA implementation does not check boundaries and computes s^(-1)==0.",
+ "PointDuplication" : "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission.",
+ "SigSize" : "The size of the signature should always be twice the number of bytes of the size of the order. But some libraries accept signatures with less bytes."
+ },
+ "schema" : "ecdsa_p1363_verify_schema.json",
+ "testGroups" : [
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "KSexBRK64-3c_kZ4KBKLrSkDJpkZ9whgacjE32xzKDg",
+ "y" : "x3h5ZOqsAOWSH7FJimD0YGdms9loUAFVjRqXTnNBUT4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "wx" : "2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838",
+ "wy" : "00c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKSexBRK64+3c/kZ4KBKLrSkDJpkZ\n9whgacjE32xzKDjHeHlk6qwA5ZIfsUmKYPRgZ2az2WhQAVWNGpdOc0FRPg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 1,
+ "comment" : "signature malleability",
+ "msg" : "313233343030",
+ "sig" : "2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 2,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "012ba3a8bd6b94d5ed80a6d9d1190a436ebccc0833490686deac8635bcb9bf536900b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 3,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 4,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "012ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1800b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 5,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 6,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "002ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1801b329f478a2bbd0a6c384ee1493b1f518276e0e4a5375928d6fcd160c11cb6d2c",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 7,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "002ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1801b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 8,
+ "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group",
+ "msg" : "313233343030",
+ "sig" : "2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e184cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b825",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 9,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 10,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 11,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 12,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 13,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 14,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 15,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000000ffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 16,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 17,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 18,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 19,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 20,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000001ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 21,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 22,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000001ffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 23,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325510000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 24,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325510000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 25,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 26,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 27,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 28,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 29,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551ffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 30,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325500000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 31,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325500000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 32,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 33,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 34,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 35,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 36,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550ffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 37,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325520000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 38,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325520000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 39,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 40,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 41,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 42,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 43,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552ffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 44,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 45,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 46,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 47,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 48,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 49,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 50,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000ffffffffffffffffffffffffffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 51,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 52,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 53,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 54,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 55,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 56,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 57,
+ "comment" : "Signature with special case values for r and s",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000001000000000000000000000000ffffffff00000001000000000000000000000001000000000000000000000000",
+ "result" : "invalid",
+ "flags" : [
+ "EdgeCase"
+ ]
+ },
+ {
+ "tcId" : 58,
+ "comment" : "Edge case for Shamir multiplication",
+ "msg" : "3639383139",
+ "sig" : "64a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e6af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 59,
+ "comment" : "special case hash",
+ "msg" : "343236343739373234",
+ "sig" : "16aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e9",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 60,
+ "comment" : "special case hash",
+ "msg" : "37313338363834383931",
+ "sig" : "9cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c882093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c32",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 61,
+ "comment" : "special case hash",
+ "msg" : "3130333539333331363638",
+ "sig" : "73b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa432f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c88634",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 62,
+ "comment" : "special case hash",
+ "msg" : "33393439343031323135",
+ "sig" : "bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3ddbdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 63,
+ "comment" : "special case hash",
+ "msg" : "31333434323933303739",
+ "sig" : "204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd51cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b52",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 64,
+ "comment" : "special case hash",
+ "msg" : "33373036323131373132",
+ "sig" : "ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0399ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c7",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 65,
+ "comment" : "special case hash",
+ "msg" : "333433363838373132",
+ "sig" : "060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b8d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d3610",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 66,
+ "comment" : "special case hash",
+ "msg" : "31333531353330333730",
+ "sig" : "9f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831db26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e9902",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 67,
+ "comment" : "special case hash",
+ "msg" : "36353533323033313236",
+ "sig" : "a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b720aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 68,
+ "comment" : "special case hash",
+ "msg" : "31353634333436363033",
+ "sig" : "fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db93df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d21350",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 69,
+ "comment" : "special case hash",
+ "msg" : "34343239353339313137",
+ "sig" : "b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff2",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 70,
+ "comment" : "special case hash",
+ "msg" : "3130393533323631333531",
+ "sig" : "3b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a84c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d99258",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 71,
+ "comment" : "special case hash",
+ "msg" : "35393837333530303431",
+ "sig" : "30c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf47c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 72,
+ "comment" : "special case hash",
+ "msg" : "33343633303036383738",
+ "sig" : "38686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f52067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 73,
+ "comment" : "special case hash",
+ "msg" : "39383137333230323837",
+ "sig" : "44a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf2d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e86",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 74,
+ "comment" : "special case hash",
+ "msg" : "33323232303431303436",
+ "sig" : "2ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e97d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f9",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 75,
+ "comment" : "special case hash",
+ "msg" : "36363636333037313034",
+ "sig" : "bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8ff6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c7",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 76,
+ "comment" : "special case hash",
+ "msg" : "31303335393531383938",
+ "sig" : "50f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab244726",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 77,
+ "comment" : "special case hash",
+ "msg" : "31383436353937313935",
+ "sig" : "f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d3f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 78,
+ "comment" : "special case hash",
+ "msg" : "33313336303436313839",
+ "sig" : "9505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7ac60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c5021",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 79,
+ "comment" : "special case hash",
+ "msg" : "32363633373834323534",
+ "sig" : "bbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d9d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f00",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 80,
+ "comment" : "special case hash",
+ "msg" : "31363532313030353234",
+ "sig" : "2ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e7ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a19878",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 81,
+ "comment" : "special case hash",
+ "msg" : "35373438303831363936",
+ "sig" : "54e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c592ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 82,
+ "comment" : "special case hash",
+ "msg" : "36333433393133343638",
+ "sig" : "5291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc3",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 83,
+ "comment" : "special case hash",
+ "msg" : "31353431313033353938",
+ "sig" : "207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf7592767",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 84,
+ "comment" : "special case hash",
+ "msg" : "3130343738353830313238",
+ "sig" : "6554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f929",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 85,
+ "comment" : "special case hash",
+ "msg" : "3130353336323835353638",
+ "sig" : "a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfce99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 86,
+ "comment" : "special case hash",
+ "msg" : "393533393034313035",
+ "sig" : "975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf7faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf919622",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 87,
+ "comment" : "special case hash",
+ "msg" : "393738383438303339",
+ "sig" : "5694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e0dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa4",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 88,
+ "comment" : "special case hash",
+ "msg" : "33363130363732343432",
+ "sig" : "a0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba65e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c65424339",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 89,
+ "comment" : "special case hash",
+ "msg" : "31303534323430373035",
+ "sig" : "614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a88737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 90,
+ "comment" : "special case hash",
+ "msg" : "35313734343438313937",
+ "sig" : "bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa6bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 91,
+ "comment" : "special case hash",
+ "msg" : "31393637353631323531",
+ "sig" : "499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad242c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d693",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 92,
+ "comment" : "special case hash",
+ "msg" : "33343437323533333433",
+ "sig" : "08f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b29d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 93,
+ "comment" : "special case hash",
+ "msg" : "333638323634333138",
+ "sig" : "be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c89",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 94,
+ "comment" : "special case hash",
+ "msg" : "33323631313938363038",
+ "sig" : "15e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a1939123",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 95,
+ "comment" : "special case hash",
+ "msg" : "39363738373831303934",
+ "sig" : "352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad1348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c6",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 96,
+ "comment" : "special case hash",
+ "msg" : "34393538383233383233",
+ "sig" : "4a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb3a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc5981725782",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 97,
+ "comment" : "special case hash",
+ "msg" : "383234363337383337",
+ "sig" : "eacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e967451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d1",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 98,
+ "comment" : "special case hash",
+ "msg" : "3131303230383333373736",
+ "sig" : "2f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 99,
+ "comment" : "special case hash",
+ "msg" : "313333383731363438",
+ "sig" : "ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b330021979938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 100,
+ "comment" : "special case hash",
+ "msg" : "333232313434313632",
+ "sig" : "81f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f74300",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 101,
+ "comment" : "special case hash",
+ "msg" : "3130363836363535353436",
+ "sig" : "dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca808048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e7",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 102,
+ "comment" : "special case hash",
+ "msg" : "3632313535323436",
+ "sig" : "ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576293320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c199345",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 103,
+ "comment" : "special case hash",
+ "msg" : "37303330383138373734",
+ "sig" : "ac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a8",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 104,
+ "comment" : "special case hash",
+ "msg" : "35393234353233373434",
+ "sig" : "677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f76b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db55",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 105,
+ "comment" : "special case hash",
+ "msg" : "31343935353836363231",
+ "sig" : "479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b2443",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 106,
+ "comment" : "special case hash",
+ "msg" : "34303035333134343036",
+ "sig" : "43dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a31dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f49584389772",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 107,
+ "comment" : "special case hash",
+ "msg" : "33303936343537353132",
+ "sig" : "5b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff1145b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d75",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 108,
+ "comment" : "special case hash",
+ "msg" : "32373834303235363230",
+ "sig" : "5e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06fb1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c20",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 109,
+ "comment" : "special case hash",
+ "msg" : "32363138373837343138",
+ "sig" : "0671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32edb1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 110,
+ "comment" : "special case hash",
+ "msg" : "31363432363235323632",
+ "sig" : "7673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a3dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 111,
+ "comment" : "special case hash",
+ "msg" : "36383234313839343336",
+ "sig" : "7f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b5249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 112,
+ "comment" : "special case hash",
+ "msg" : "343834323435343235",
+ "sig" : "914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "CtmVACiNRmlAAx1yqfVEWk1DeEZAhVvwpph00t5f4QM",
+ "y" : "xQEebvLELc1Q1dPSn5mubrosgMkkT0xUIvCXn_DDul4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "040ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e",
+ "wx" : "0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103",
+ "wy" : "00c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECtmVACiNRmlAAx1yqfVEWk1DeEZA\nhVvwpph00t5f4QPFAR5u8sQtzVDV09Kfma5uuiyAySRPTFQi8Jef8MO6Xg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 113,
+ "comment" : "k*G has a large x-coordinate",
+ "msg" : "313233343030",
+ "sig" : "000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 114,
+ "comment" : "r too large",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000001000000000000000000000000fffffffffffffffffffffffcffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "qwX9nQ3ia5zm9IGWUtn8aRk9CqOY8PuoAT4JxYIgRVQ",
+ "y" : "GSNScSKMeGdZCV0St1rwaS3UED8Z9qjDL0lDWh6bjUU"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04ab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45",
+ "wx" : "00ab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c582204554",
+ "wy" : "19235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004ab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqwX9nQ3ia5zm9IGWUtn8aRk9CqOY\n8PuoAT4JxYIgRVQZI1JxIox4Z1kJXRK3WvBpLdQQPxn2qMMvSUNaHpuNRQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 115,
+ "comment" : "r,s are large",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "gJhPOaH_OKhqaKpCAba-Xfv-z4diGXELB7rfb91MbFY",
+ "y" : "Ef65c5DZgm56Bt-0GHHJQNdEFe08rCCJ8URQGbtV7ZU"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95",
+ "wx" : "0080984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c56",
+ "wy" : "11feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgJhPOaH/OKhqaKpCAba+Xfv+z4di\nGXELB7rfb91MbFYR/rlzkNmCbnoG37QYcclA10QV7TysIInxRFAZu1XtlQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 116,
+ "comment" : "r and s^-1 have a large Hamming weight",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd4",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "QgG0JylEIBwylPW6qaMjK23Wh0lfzBmnCpW8YCtPfAU",
+ "y" : "lcN-up7oFxwbtaxv6vdTvDb0Y-Ou8WYpVywMCo-wgA4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "044201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e",
+ "wx" : "4201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c05",
+ "wy" : "0095c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQgG0JylEIBwylPW6qaMjK23Wh0lf\nzBmnCpW8YCtPfAWVw366nugXHBu1rG/q91O8NvRj467xZilXLAwKj7CADg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 117,
+ "comment" : "r and s^-1 have a large Hamming weight",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd27b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "pxr2TeUSakpOAreSLWbOlBXOiKTJ0lUU2RCCyHJayVc",
+ "y" : "XUdyPI--WAuzaf7JwmZdjjCkNbmTJkVILnyfEehyKWs"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b",
+ "wx" : "00a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957",
+ "wy" : "5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpxr2TeUSakpOAreSLWbOlBXOiKTJ\n0lUU2RCCyHJayVddR3I8j75YC7Np/snCZl2OMKQ1uZMmRUgufJ8R6HIpaw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 118,
+ "comment" : "small r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 119,
+ "comment" : "incorrect size of signature",
+ "msg" : "313233343030",
+ "sig" : "0501",
+ "result" : "acceptable",
+ "flags" : [
+ "SigSize"
+ ]
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "ZifOxPBzHqI_wpMfkOvlt1cvWX0g3wj8KzHujvFrFXI",
+ "y" : "YXDtd9jQoU_FycPEyb5_DT7hj3CbsnXq8gc-JY_mlKU"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "046627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5",
+ "wx" : "6627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b1572",
+ "wy" : "6170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZifOxPBzHqI/wpMfkOvlt1cvWX0g\n3wj8KzHujvFrFXJhcO132NChT8XJw8TJvn8NPuGPcJuyderyBz4lj+aUpQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 120,
+ "comment" : "small r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000003",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 121,
+ "comment" : "incorrect size of signature",
+ "msg" : "313233343030",
+ "sig" : "0503",
+ "result" : "acceptable",
+ "flags" : [
+ "SigSize"
+ ]
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "WnyIJehWkczh9edUTFTnPxSvwBDLcxNDJiyn7Fp39b8",
+ "y" : "727fYqRJfBvXsUf7bD0irzw5v86V8w4ToW09eygS-BM"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813",
+ "wx" : "5a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bf",
+ "wy" : "00ef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWnyIJehWkczh9edUTFTnPxSvwBDL\ncxNDJiyn7Fp39b/vbt9ipEl8G9exR/tsPSKvPDm/zpXzDhOhbT17KBL4Ew==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 122,
+ "comment" : "small r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 123,
+ "comment" : "incorrect size of signature",
+ "msg" : "313233343030",
+ "sig" : "0505",
+ "result" : "acceptable",
+ "flags" : [
+ "SigSize"
+ ]
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "y-DCkTLNc4Nk_t1gMVKZDASOXi__mW2IP6bKynl4xzc",
+ "y" : "cK9qjORMtBIksmA2BvTATRiOgL_3zDGtUYnUqw1w6ME"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1",
+ "wx" : "00cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c737",
+ "wy" : "70af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEy+DCkTLNc4Nk/t1gMVKZDASOXi//\nmW2IP6bKynl4xzdwr2qM5Ey0EiSyYDYG9MBNGI6Av/fMMa1RidSrDXDowQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 124,
+ "comment" : "small r and s",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000006",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 125,
+ "comment" : "incorrect size of signature",
+ "msg" : "313233343030",
+ "sig" : "0506",
+ "result" : "acceptable",
+ "flags" : [
+ "SigSize"
+ ]
+ },
+ {
+ "tcId" : 126,
+ "comment" : "r is larger than n",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325560000000000000000000000000000000000000000000000000000000000000006",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "S-QXgJcALw3qto8NmhMODtM6Z5XQKiB5bbg0RLA34Tk",
+ "y" : "IPEwUeDuzc_OTazqD1DR8kfKpmnxk8G0B1tRriltLVY"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "044be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56",
+ "wx" : "4be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e139",
+ "wy" : "20f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES+QXgJcALw3qto8NmhMODtM6Z5XQ\nKiB5bbg0RLA34Tkg8TBR4O7Nz85NrOoPUNHyR8qmafGTwbQHW1GuKW0tVg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 127,
+ "comment" : "s is larger than n",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000005ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd8",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "0Pc3kiA3Fq_UvkMp-qSNJp8VMT67ujedd4PJe_PokNk",
+ "y" : "lx9KMgZgW-wheCv14nXHFEF-j1ZlSea8aGkNI2PInME"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1",
+ "wx" : "00d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9",
+ "wy" : "00971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0Pc3kiA3Fq/UvkMp+qSNJp8VMT67\nujedd4PJe/PokNmXH0oyBmBb7CF4K/XidccUQX6PVmVJ5rxoaQ0jY8icwQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 128,
+ "comment" : "small r and s^-1",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000000000000000000000000001008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "SDiyvjWmJ2qA754igUD52bls6Dt6JU9xzN67uAVM4F8",
+ "y" : "-py8EjyRmxngAjgZjQQGkEO9ZgqCiBQFH8uKrHOKbGs"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "044838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b",
+ "wx" : "4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05f",
+ "wy" : "00fa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESDiyvjWmJ2qA754igUD52bls6Dt6\nJU9xzN67uAVM4F/6nLwSPJGbGeACOBmNBAaQQ71mCoKIFAUfy4qsc4psaw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 129,
+ "comment" : "smallish r and s^-1",
+ "msg" : "313233343030",
+ "sig" : "000000000000000000000000000000000000000000000000002d9b4d347952d6ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "c5OYPKMKUgu8R4PcmWB0aqtETvUgwKjncRGapOdLD2Q",
+ "y" : "6de-GrAaC_Ym5wmGPmpIbbrzJ5OvzPd04sbNJ7GFdSY"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "047393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526",
+ "wx" : "7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64",
+ "wy" : "00e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200047393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc5OYPKMKUgu8R4PcmWB0aqtETvUg\nwKjncRGapOdLD2Tp174asBoL9ibnCYY+akhtuvMnk6/M93Tixs0nsYV1Jg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 130,
+ "comment" : "100-bit r and small s^-1",
+ "msg" : "313233343030",
+ "sig" : "000000000000000000000000000000000000001033e67e37b32b445580bf4eff8b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "WsMxoRA_6WZpc3nzVqk381BYigVHfjCIUbilAtXfzcU",
+ "y" : "_pmT30tXk5srjaCVv215QmUgTP4DvplaAuZdQIyHHAs"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b",
+ "wx" : "5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5",
+ "wy" : "00fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWsMxoRA/6WZpc3nzVqk381BYigVH\nfjCIUbilAtXfzcX+mZPfS1eTmyuNoJW/bXlCZSBM/gO+mVoC5l1AjIccCw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 131,
+ "comment" : "small r and 100 bit s^-1",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "HSCb6N4t6HcJWjmdOQTHTMRY2Sbie7jljl6uV2fEFQk",
+ "y" : "3VngTCFPexjc41H8KlSYk6aGDoAWPzjMYKTyydBA2Mk"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "041d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9",
+ "wx" : "1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509",
+ "wy" : "00dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200041d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHSCb6N4t6HcJWjmdOQTHTMRY2Sbi\ne7jljl6uV2fEFQndWeBMIU97GNzjUfwqVJiTpoYOgBY/OMxgpPLJ0EDYyQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 132,
+ "comment" : "100-bit r and s^-1",
+ "msg" : "313233343030",
+ "sig" : "00000000000000000000000000000000000000062522bbd3ecbe7c39e93e7c25ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "CDU5--5EYl46yq-i_LQTSTks7wYzobj6vs7gwTOxDpk",
+ "y" : "kVwevnvwDfhTUZZ3ClgEeuKkAvJjJrt9QdTXYWM3kR4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e",
+ "wx" : "083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99",
+ "wy" : "00915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECDU5++5EYl46yq+i/LQTSTks7wYz\nobj6vs7gwTOxDpmRXB6+e/AN+FNRlncKWAR64qQC8mMmu31B1NdhYzeRHg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 133,
+ "comment" : "r and s^-1 are close to n",
+ "msg" : "313233343030",
+ "sig" : "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d5555555550000000055555555555555553ef7a8e48d07df81a693439654210c70",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "ius2inAnpNZKveo3OQwMHWom85ni2XNN4es9Dhk3OHQ",
+ "y" : "Bb0Tg0cV4duum4dc8HvVXhtmkcf3U2rvOxm_ekrfV20"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "048aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d",
+ "wx" : "008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e19373874",
+ "wy" : "05bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200048aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEius2inAnpNZKveo3OQwMHWom85ni\n2XNN4es9Dhk3OHQFvRODRxXh266bh1zwe9VeG2aRx/dTau87Gb96St9XbQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 134,
+ "comment" : "s == 1",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000001",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 135,
+ "comment" : "s == 0",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c700000000000000000000000000000000000000000000000000000000000000000",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "tTPUaV3VuMXgd1flXm5Rb34siPoCOeI_YOjsB91w8oc",
+ "y" : "GxNO5YzFgyeEVoY_M8OoXYgffUo5hQFD4p1OrwCa_kc"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47",
+ "wx" : "00b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f287",
+ "wy" : "1b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtTPUaV3VuMXgd1flXm5Rb34siPoC\nOeI/YOjsB91w8ocbE07ljMWDJ4RWhj8zw6hdiB99SjmFAUPinU6vAJr+Rw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 136,
+ "comment" : "point at infinity during verify",
+ "msg" : "313233343030",
+ "sig" : "7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8555555550000000055555555555555553ef7a8e48d07df81a693439654210c70",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "9Q03G5G_sdfRThMjUjvDqoy_LFf54oTeYoyLRTZ4e4Y",
+ "y" : "-UrYh6yU1SckfNLn0MixKRxVPJcwQFOAsUy7IJ9fot0"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd",
+ "wx" : "00f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86",
+ "wy" : "00f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9Q03G5G/sdfRThMjUjvDqoy/LFf5\n4oTeYoyLRTZ4e4b5StiHrJTVJyR80ufQyLEpHFU8lzBAU4CxTLsgn1+i3Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 137,
+ "comment" : "edge case for signature malleability",
+ "msg" : "313233343030",
+ "sig" : "7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "aOxuKY6v4WU5FWzlehSwSnBHwiG6_DpYLq6w2FfE2UY",
+ "y" : "l77RrxeFARf9s5sjJPIgpWmO0WxCaiczW7OFrIym-zA"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0468ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30",
+ "wx" : "68ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d946",
+ "wy" : "0097bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000468ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaOxuKY6v4WU5FWzlehSwSnBHwiG6\n/DpYLq6w2FfE2UaXvtGvF4UBF/2zmyMk8iClaY7RbEJqJzNbs4WsjKb7MA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 138,
+ "comment" : "edge case for signature malleability",
+ "msg" : "313233343030",
+ "sig" : "7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a97fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "adoDZHNNLlMP7OlAGSZf77eBoPGwj2yIl732VXknyLg",
+ "y" : "ZtLTx9zVGLI9cmlg8Gmtcakz2G74q7zOiyD3HiqEcAI"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0469da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002",
+ "wx" : "69da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b8",
+ "wy" : "66d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000469da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEadoDZHNNLlMP7OlAGSZf77eBoPGw\nj2yIl732VXknyLhm0tPH3NUYsj1yaWDwaa1xqTPYbvirvM6LIPceKoRwAg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 139,
+ "comment" : "u1 == 1",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c70bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "2K3AACOo7cAlduK2Pj4wYhpHHisjIGIBh78GehrB_zI",
+ "y" : "M-K1DsCYB6zLNhMf_5XtEqCahrTqlpCqMoYVdrojYuE"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04d8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1",
+ "wx" : "00d8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff32",
+ "wy" : "33e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2K3AACOo7cAlduK2Pj4wYhpHHisj\nIGIBh78GehrB/zIz4rUOwJgHrMs2Ex//le0SoJqGtOqWkKoyhhV2uiNi4Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 140,
+ "comment" : "u1 == n - 1",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c7044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "NiOslzztClb6bYgvA6fVx-3KAs_HskAfqzaQ2-dat4U",
+ "y" : "jbBpCOZLKGE9pyV-c385eT2o5xO6BkO5LpuzJSvn-P4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "043623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe",
+ "wx" : "3623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab785",
+ "wy" : "008db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENiOslzztClb6bYgvA6fVx+3KAs/H\nskAfqzaQ2+dat4WNsGkI5ksoYT2nJX5zfzl5PajnE7oGQ7kum7MlK+f4/g==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 141,
+ "comment" : "u2 == 1",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c70555555550000000055555555555555553ef7a8e48d07df81a693439654210c70",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "zwTqd-liJSPYlLk_9S3DAnsxlZUDtvo4kOXgQmP5IvE",
+ "y" : "6FKPt8AGs5g8i4QA5XtO1xdAwvOXVDiCEZm-3q7Ksuk"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9",
+ "wx" : "00cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1",
+ "wy" : "00e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzwTqd+liJSPYlLk/9S3DAnsxlZUD\ntvo4kOXgQmP5IvHoUo+3wAazmDyLhADle07XF0DC85dUOIIRmb7ersqy6Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 142,
+ "comment" : "u2 == n - 1",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c70aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "23osihq1c-WSncJAd7UI1-aD1JInmWvaPp942-_3c1A",
+ "y" : "T0F_O8mogHXC4KrdWhMxFzDPfMdqgvEaNurwimyZogY"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206",
+ "wx" : "00db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff77350",
+ "wy" : "4f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE23osihq1c+WSncJAd7UI1+aD1JIn\nmWvaPp942+/3c1BPQX87yaiAdcLgqt1aEzEXMM98x2qC8Ro26vCKbJmiBg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 143,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffde91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "3q0Rx6WzloYvIZdNxHUvre_5lO_pu9BatBN2XqgLbh8",
+ "y" : "HePwZA6Kxu3Pic_1PEDiZbuUB4o0NzbfB6oDGPx_4f8"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff",
+ "wx" : "00dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f",
+ "wy" : "1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3q0Rx6WzloYvIZdNxHUvre/5lO/p\nu9BatBN2XqgLbh8d4/BkDorG7c+Jz/U8QOJlu5QHijQ3Nt8HqgMY/H/h/w==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 144,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "0LxHLg18geuu06bvlsGGE7sf6m-ZQyb76A4A395nx-k",
+ "y" : "mGxyPqSEPUg4m5RvZK1WyDrXD_F7qFM1Zn0bufphnv0"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd",
+ "wx" : "00d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9",
+ "wy" : "00986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0LxHLg18geuu06bvlsGGE7sf6m+Z\nQyb76A4A395nx+mYbHI+pIQ9SDiblG9krVbIOtcP8XuoUzVmfRu5+mGe/Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 145,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "oKRMqUfWairLc2AIucCNGrKtA3duAmQPeEldRY3VHDI",
+ "y" : "Yzf-XPjEYEsfHECdwthy1ClKR2JCDfQ6MKI5LkBCat0"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add",
+ "wx" : "00a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c32",
+ "wy" : "6337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoKRMqUfWairLc2AIucCNGrKtA3du\nAmQPeEldRY3VHDJjN/5c+MRgSx8cQJ3C2HLUKUpHYkIN9DowojkuQEJq3Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 146,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "ycIRUpDQCLRftl-tD2AjiSmMJUILd1AZ1Ctiw86Klrc",
+ "y" : "OHfSWoCA3ALZh8pzDwQFwsnb76xG-eYBzD8G6XE5c_0"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd",
+ "wx" : "00c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b7",
+ "wy" : "3877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEycIRUpDQCLRftl+tD2AjiSmMJUIL\nd1AZ1Ctiw86Klrc4d9JagIDcAtmHynMPBAXCydvvrEb55gHMPwbpcTlz/Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 147,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "Xsoe9MKH3dxmuLzPG4jookwAGJYvPF5--oO8Gl_2Az4",
+ "y" : "XnnEyywkW4xFq9zoqOTadY2SpgfDLNQH7K7yLxyTSnE"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71",
+ "wx" : "5eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e",
+ "wy" : "5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXsoe9MKH3dxmuLzPG4jookwAGJYv\nPF5++oO8Gl/2Az5eecTLLCRbjEWr3Oio5Np1jZKmB8Ms1AfsrvIvHJNKcQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 148,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f91",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "XKqgMOf98OSTa8erWpY1PgoB5BMMP4vyLUc-MXAppHo",
+ "y" : "3ratxGL3BY8qINNx6XAiVOmyAWQgBbPO2pJrQrF4vvk"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9",
+ "wx" : "5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47a",
+ "wy" : "00deb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXKqgMOf98OSTa8erWpY1PgoB5BMM\nP4vyLUc+MXAppHretq3EYvcFjyog03HpcCJU6bIBZCAFs87akmtCsXi++Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 149,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "wv0gusBuVVu4rAzmnrHqIPg6H8NQHIpmRpsaMfYZsJg",
+ "y" : "YjcFB3n1K2Fb17jXaiX8lcou0yUlx18n_8h6w5fmy68"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf",
+ "wx" : "00c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b098",
+ "wy" : "6237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwv0gusBuVVu4rAzmnrHqIPg6H8NQ\nHIpmRpsaMfYZsJhiNwUHefUrYVvXuNdqJfyVyi7TJSXHXyf/yHrDl+bLrw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 150,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "P9ahyn93-zsLvnJsNyAQBoQm4R6mrnjOF77a5LuobO0",
+ "y" : "A85VFkBr-M-quHRerBzWkBitb1C1Rhhy3fxW4Ns8j_Q"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "043fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4",
+ "wx" : "3fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced",
+ "wy" : "03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEP9ahyn93+zsLvnJsNyAQBoQm4R6m\nrnjOF77a5LuobO0DzlUWQGv4z6q4dF6sHNaQGK1vULVGGHLd/Fbg2zyP9A==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 151,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d6",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "nLjlHielrjtiSmDW3DJzTkmJ2yDpvKPt4e33sIaRERQ",
+ "y" : "tMEEqzxnfks21lVuitX1I0EKGfLid6qJX8VzIrRCdUQ"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "049cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544",
+ "wx" : "009cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114",
+ "wy" : "00b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200049cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLjlHielrjtiSmDW3DJzTkmJ2yDp\nvKPt4e33sIaRERS0wQSrPGd+SzbWVW6K1fUjQQoZ8uJ3qolfxXMitEJ1RA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 152,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd29798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d8",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "o-UsFW3K8QUCYgt5VbwrQLx47z1WnhIjwmJRLY9JYCo",
+ "y" : "SiA58xwQlwJK08yG5XMh3gMjVUY0hhZM8ZKUSXffFH8"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04a3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f",
+ "wx" : "00a3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a",
+ "wy" : "4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+UsFW3K8QUCYgt5VbwrQLx47z1W\nnhIjwmJRLY9JYCpKIDnzHBCXAkrTzIblcyHeAyNVRjSGFkzxkpRJd98Ufw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 153,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dd",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "8Zt4kocg1b7o5nD7kAEPsVw3v5G1ilFXw_PAWbJlXog",
+ "y" : "z3AeyWL7ShHc8nP13DV-WEaFYMfP65QtB0q9QykmBQk"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04f19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509",
+ "wx" : "00f19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88",
+ "wy" : "00cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8Zt4kocg1b7o5nD7kAEPsVw3v5G1\nilFXw/PAWbJlXojPcB7JYvtKEdzyc/XcNX5YRoVgx8/rlC0HSr1DKSYFCQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 154,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd16e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1ba",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "g6dERZ7N-wGlz1KyegW7czdILSQvI117TLiTRVRckKg",
+ "y" : "wF1JM3uWSYEyh96f_pA1X9kF3188MpRYKBIfN8xQ3m4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0483a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e",
+ "wx" : "0083a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8",
+ "wy" : "00c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000483a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg6dERZ7N+wGlz1KyegW7czdILSQv\nI117TLiTRVRckKjAXUkze5ZJgTKH3p/+kDVf2QXfXzwylFgoEh83zFDebg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 155,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd2252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a97",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "3RPGs0xWmC3a4STwOd_SP0sZu-iM7o5SiuUeXW86Idc",
+ "y" : "v61MLm8mP-XrWcqXTQOfwOTDNFaS-1Mgva5L07QqRf8"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff",
+ "wx" : "00dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7",
+ "wy" : "00bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3RPGs0xWmC3a4STwOd/SP0sZu+iM\n7o5SiuUeXW86Ide/rUwubyY/5etZypdNA5/A5MM0VpL7UyC9rkvTtCpF/w==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 156,
+ "comment" : "edge case for u1",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd81ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "Z-b2Wc3ehpovZfCU6U5bTfrWNrv5UZL-7tAbDz3rdGA",
+ "y" : "o34KUfJYt661Hf5ZL1z9VoW75YcSyNkjPGKIZDfDi6A"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0467e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0",
+ "wx" : "67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460",
+ "wy" : "00a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000467e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZ+b2Wc3ehpovZfCU6U5bTfrWNrv5\nUZL+7tAbDz3rdGCjfgpR8li3rrUd/lkvXP1WhbvlhxLI2SM8YohkN8OLoA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 157,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "LrZBJQWuwFxlRfApkyCH5JDQVRHo7B9Zlhe7Nn-eyq8",
+ "y" : "gF9R78xIA0A_mxrgEkiQ8GpD_tzdsxgw9maa8pKJXLA"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "042eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0",
+ "wx" : "2eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf",
+ "wy" : "00805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELrZBJQWuwFxlRfApkyCH5JDQVRHo\n7B9Zlhe7Nn+eyq+AX1HvzEgDQD+bGuASSJDwakP+3N2zGDD2ZprykolcsA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 158,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "hNtkWGjqs146n9gOBW4uhVQ146a2jXWlCoVGJf4NfzU",
+ "y" : "bSWJrGVe3JoR7z4HXt3amr-S5yFxVw73v0Oi7jkzjP4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0484db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe",
+ "wx" : "0084db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f35",
+ "wy" : "6d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000484db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhNtkWGjqs146n9gOBW4uhVQ146a2\njXWlCoVGJf4NfzVtJYmsZV7cmhHvPgde3dqav5LnIXFXDve/Q6LuOTOM/g==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 159,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "kbnkfFYnhmLXXAmDsiyo6mqlBZt6L_djfrKXXjhq1mM",
+ "y" : "SaqP8oPQ93wY1tEdwGIWX9E8PAMQZ5wUCDAqFoVOz70"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0491b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd",
+ "wx" : "0091b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad663",
+ "wy" : "49aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000491b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkbnkfFYnhmLXXAmDsiyo6mqlBZt6\nL/djfrKXXjhq1mNJqo/yg9D3fBjW0R3AYhZf0Tw8AxBnnBQIMCoWhU7PvQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 160,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd66755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf2",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "8-wvE8rwTQGStH-0xTEfttTcawqegC5TJ_fsXujkg00",
+ "y" : "-X4-Rot9Dbhn1uz-geKw-VMd-H79tHwTOKwyH-_lpDI"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432",
+ "wx" : "00f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834d",
+ "wy" : "00f97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8+wvE8rwTQGStH+0xTEfttTcawqe\ngC5TJ/fsXujkg035fj5Gi30NuGfW7P6B4rD5Ux34fv20fBM4rDIf7+WkMg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 161,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd55a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "2SsgCu_Ktqx9r9msry-hCzGAI1uPRrRQPkaTxnD8zIg",
+ "y" : "XvLzrr9bMXR1M2JWdo98Ge-3NS0n5MzK3IW2uKuSLHI"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72",
+ "wx" : "00d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc88",
+ "wy" : "5ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2SsgCu/Ktqx9r9msry+hCzGAI1uP\nRrRQPkaTxnD8zIhe8vOuv1sxdHUzYlZ2j3wZ77c1LSfkzMrchba4q5Iscg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 162,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "Cog2HrkuzKJiWzjl-Yu6u5a_F5s9dvxIFAo7zYgVI80",
+ "y" : "5r31YDP4SlBUA1WXN12QhmqiyWuGpBzPbt6_RymK1Ik"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "040a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489",
+ "wx" : "0a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cd",
+ "wy" : "00e6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECog2HrkuzKJiWzjl+Yu6u5a/F5s9\ndvxIFAo7zYgVI83mvfVgM/hKUFQDVZc3XZCGaqLJa4akHM9u3r9HKYrUiQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 163,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc8600",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "0PsXzNj6_oJ-DBr8XY2ANm4rIOfxSlY6K6UEadhDdeg",
+ "y" : "aGEladOeK7n1VDVVZGRt6ZrGAsxjSc-MHiNqfedjfZM"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93",
+ "wx" : "00d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e8",
+ "wy" : "68612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0PsXzNj6/oJ+DBr8XY2ANm4rIOfx\nSlY6K6UEadhDdehoYSVp054rufVUNVVkZG3pmsYCzGNJz4weI2p952N9kw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 164,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "g28zu8HcDT06u87w2R8R4qxBgQdsmvCiKx5DCdPtsnY",
+ "y" : "mrRD_2-QHjDHc4Z1gpl8K-wrDLgSDXYCNvOpW76IH3U"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75",
+ "wx" : "00836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb276",
+ "wy" : "009ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg28zu8HcDT06u87w2R8R4qxBgQds\nmvCiKx5DCdPtsnaatEP/b5AeMMdzhnWCmXwr7CsMuBINdgI286lbvogfdQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 165,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "kvmfvpc-1KKZcZuu5LQydBI3A03sjXK6UQPLM-Vf7rg",
+ "y" : "Az3Q6RE0xzQXSInz688behrAV2cokoDuenlM69bmlpc"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0492f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697",
+ "wx" : "0092f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8",
+ "wy" : "033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000492f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkvmfvpc+1KKZcZuu5LQydBI3A03s\njXK6UQPLM+Vf7rgDPdDpETTHNBdIifPrzxt6GsBXZyiSgO56eUzr1uaWlw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 166,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "01uljaMBl9N45hjsD6fi4tEs_9c-u7IEnRMLukNK8J4",
+ "y" : "_4OYbmh15B6kMrdYWkmzpsd8uzxHkZ-OgodMeUY1wdI"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2",
+ "wx" : "00d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09e",
+ "wy" : "00ff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01uljaMBl9N45hjsD6fi4tEs/9c+\nu7IEnRMLukNK8J7/g5huaHXkHqQyt1haSbOmx3y7PEeRn46Ch0x5RjXB0g==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 167,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "hlHOSQ8bRtc_P_R1FJvikTZpczSlGdfdqwclyNB5MiQ",
+ "y" : "4RxlvYypLci8mugpEfC1J1HOId2QA65gkAvYJfWQzCg"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "048651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28",
+ "wx" : "008651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224",
+ "wy" : "00e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200048651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhlHOSQ8bRtc/P/R1FJvikTZpczSl\nGdfdqwclyNB5MiThHGW9jKktyLya6CkR8LUnUc4h3ZADrmCQC9gl9ZDMKA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 168,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "bY4bEsgxoNqHlWUP-V8QHtkh2eL3KxWxzaypgmuc_G0",
+ "y" : "721j4rxcCJVwOUpLyfiS1ebHpqY3sgRppYwQatSGvzc"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "046d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37",
+ "wx" : "6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6d",
+ "wy" : "00ef6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbY4bEsgxoNqHlWUP+V8QHtkh2eL3\nKxWxzaypgmuc/G3vbWPivFwIlXA5SkvJ+JLV5sempjeyBGmljBBq1Ia/Nw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 169,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "CuWAuukztO8pl8vbsJIjKMqaQQ9ieg99_yTLTZIOFUI",
+ "y" : "iRHn-Mw2WoqI64FCGjYczCuZ4wnY3Nmpi6g8OUnYk-M"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "040ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3",
+ "wx" : "0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e1542",
+ "wy" : "008911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECuWAuukztO8pl8vbsJIjKMqaQQ9i\neg99/yTLTZIOFUKJEef4zDZaiojrgUIaNhzMK5njCdjc2amLqDw5SdiT4w==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 170,
+ "comment" : "edge case for u2",
+ "msg" : "313233343030",
+ "sig" : "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "W4Ev1SGq-mmDWoSczm-962mDtELSRE_nDhNMAn_EaWM",
+ "y" : "g4pA8qNgkukATpLY2UDPVjhVDOZyzouNThXrpUmSSek"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9",
+ "wx" : "5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963",
+ "wy" : "00838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW4Ev1SGq+mmDWoSczm+962mDtELS\nRE/nDhNMAn/EaWODikDyo2CS6QBOktjZQM9WOFUM5nLOi41OFeulSZJJ6Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 171,
+ "comment" : "point duplication during verification",
+ "msg" : "313233343030",
+ "sig" : "6f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b",
+ "result" : "valid",
+ "flags" : [
+ "PointDuplication"
+ ]
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "W4Ev1SGq-mmDWoSczm-962mDtELSRE_nDhNMAn_EaWM",
+ "y" : "fHW_DFyfbRf_sW0nJr8wqceq8xqNMXRyseoUWrZtthY"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616",
+ "wx" : "5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963",
+ "wy" : "7c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW4Ev1SGq+mmDWoSczm+962mDtELS\nRE/nDhNMAn/EaWN8db8MXJ9tF/+xbScmvzCpx6rzGo0xdHKx6hRatm22Fg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 172,
+ "comment" : "duplication bug",
+ "msg" : "313233343030",
+ "sig" : "6f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b",
+ "result" : "invalid",
+ "flags" : [
+ "PointDuplication"
+ ]
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "at2oK5AmGw8xn6oNh4ZlprbaSX8JyQMXYiLDSs_vcqY",
+ "y" : "R-b1DcxArV2bWfdgK7Ii-tcaQb9eH530lZo2TGLkiNk"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "046adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9",
+ "wx" : "6adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a6",
+ "wy" : "47e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEat2oK5AmGw8xn6oNh4ZlprbaSX8J\nyQMXYiLDSs/vcqZH5vUNzECtXZtZ92ArsiL61xpBv14fnfSVmjZMYuSI2Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 173,
+ "comment" : "point with x-coordinate 0",
+ "msg" : "313233343030",
+ "sig" : "0000000000000000000000000000000000000000000000000000000000000001555555550000000055555555555555553ef7a8e48d07df81a693439654210c70",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "L8oNCkeRTed-1W5-zMMnamARIMbfAGnIJcj2oByfOCA",
+ "y" : "ZfNFCh0XxrJJiaOb6xx97PyoOE-9wpRBjl2Aezxu194"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "042fca0d0a47914de77ed56e7eccc3276a601120c6df0069c825c8f6a01c9f382065f3450a1d17c6b24989a39beb1c7decfca8384fbdc294418e5d807b3c6ed7de",
+ "wx" : "2fca0d0a47914de77ed56e7eccc3276a601120c6df0069c825c8f6a01c9f3820",
+ "wy" : "65f3450a1d17c6b24989a39beb1c7decfca8384fbdc294418e5d807b3c6ed7de"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042fca0d0a47914de77ed56e7eccc3276a601120c6df0069c825c8f6a01c9f382065f3450a1d17c6b24989a39beb1c7decfca8384fbdc294418e5d807b3c6ed7de",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL8oNCkeRTed+1W5+zMMnamARIMbf\nAGnIJcj2oByfOCBl80UKHRfGskmJo5vrHH3s/Kg4T73ClEGOXYB7PG7X3g==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 174,
+ "comment" : "point with x-coordinate 0",
+ "msg" : "313233343030",
+ "sig" : "010000000000000000000000000000000000000000000000000000000000000000003333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "3YbTtfShPoURCDt4ACCBxT_0Z_EevZilGmM9t2Zl0lA",
+ "y" : "RdXIIAyJ8voQ2Ek0kibSHY367W_41cs-G34XR068GPc"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7",
+ "wx" : "00dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d250",
+ "wy" : "45d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3YbTtfShPoURCDt4ACCBxT/0Z/Ee\nvZilGmM9t2Zl0lBF1cggDIny+hDYSTSSJtIdjfrtb/jVyz4bfhdHTrwY9w==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 175,
+ "comment" : "comparison with point at infinity ",
+ "msg" : "313233343030",
+ "sig" : "555555550000000055555555555555553ef7a8e48d07df81a693439654210c703333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "T-pVsyyzKsoMEsTNCr-05ksPWlFuV4wBZZGpP1oPvMU",
+ "y" : "19P9ELK-ZoxUeyEva7FMiPD-zTiopLLHhe075izksoA"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "044fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280",
+ "wx" : "4fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5",
+ "wy" : "00d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAET+pVsyyzKsoMEsTNCr+05ksPWlFu\nV4wBZZGpP1oPvMXX0/0Qsr5mjFR7IS9rsUyI8P7NOKiksseF7TvmLOSygA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 176,
+ "comment" : "extreme value for k and edgecase s",
+ "msg" : "313233343030",
+ "sig" : "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978555555550000000055555555555555553ef7a8e48d07df81a693439654210c70",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "xqdxUnAkIneSFwpvju5zW_Mrf5ivZp6tKZgC4y18MQc",
+ "y" : "vDtLXmWriHu9NDVys-VhkmH-Ogc-L_14QS9yaGfbWJ4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04c6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e",
+ "wx" : "00c6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107",
+ "wy" : "00bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004c6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExqdxUnAkIneSFwpvju5zW/Mrf5iv\nZp6tKZgC4y18MQe8O0teZauIe700NXKz5WGSYf46Bz4v/XhBL3JoZ9tYng==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 177,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "hRwrutCOVOx6mvmfSfA2RNbsbVmyB_7JjehafRW5Vu8",
+ "y" : "zumWAoMEUHVoS0EL6ND3SUuRqiN59gcnMZ8Q3esP6dY"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6",
+ "wx" : "00851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956ef",
+ "wy" : "00cee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhRwrutCOVOx6mvmfSfA2RNbsbVmy\nB/7JjehafRW5Vu/O6ZYCgwRQdWhLQQvo0PdJS5GqI3n2BycxnxDd6w/p1g==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 178,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "9kF8imcFhOOIZ2lJ5T2n_FWRH_aDGNG_MGEgWssZxI8",
+ "y" : "jyt0PfNK0PcmdKy3UFkpeEd5zZrJFsNmnq1DAmq21D8"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04f6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f",
+ "wx" : "00f6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f",
+ "wy" : "008f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9kF8imcFhOOIZ2lJ5T2n/FWRH/aD\nGNG/MGEgWssZxI+PK3Q980rQ9yZ0rLdQWSl4R3nNmskWw2aerUMCarbUPw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 179,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699783333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "UBQhJ3vkWl7v7GxjmTDWNgMlZa9CDPM3P1V_qn-KBkM",
+ "y" : "hnPWy2B24c_Nx9_nOEyOXKwI10UB8q5uicrRldCqE3E"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371",
+ "wx" : "501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a0643",
+ "wy" : "008673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUBQhJ3vkWl7v7GxjmTDWNgMlZa9C\nDPM3P1V/qn+KBkOGc9bLYHbhz83H3+c4TI5crAjXRQHyrm6JytGV0KoTcQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 180,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "DZNb-f_BFaUnc19ynKikyiPuAaSJSt8ONBWshOgIuzQ",
+ "y" : "MZWjdi_qKe04kSvZ6mxP3nDDBQiTpDdYUM5h2C66M8U"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "040d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5",
+ "wx" : "0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb34",
+ "wy" : "3195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDZNb+f/BFaUnc19ynKikyiPuAaSJ\nSt8ONBWshOgIuzQxlaN2L+op7TiRK9nqbE/ecMMFCJOkN1hQzmHYLrozxQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 181,
+ "comment" : "extreme value for k",
+ "msg" : "313233343030",
+ "sig" : "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997816a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "Xln1Bwhka-iliTVQFDCOYLZo-2cBliBsQedI5k5NyiE",
+ "y" : "XeN_7lyXvK9xRNW0WZgvUu7q-98Dqsuv7zjiE2JKAd4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "045e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de",
+ "wx" : "5e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca21",
+ "wy" : "5de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXln1Bwhka+iliTVQFDCOYLZo+2cB\nliBsQedI5k5NyiFd43/uXJe8r3FE1bRZmC9S7ur73wOqy6/vOOITYkoB3g==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 182,
+ "comment" : "extreme value for k and edgecase s",
+ "msg" : "313233343030",
+ "sig" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296555555550000000055555555555555553ef7a8e48d07df81a693439654210c70",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "Fp-3lzJYQ_r_L3pbVEXani_WIm9--Q7wv-kkEEsC244",
+ "y" : "e7uN5mLHubHPmyL3ouWCvUbVgdaIeO-yuGGxMdih1mc"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667",
+ "wx" : "169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e",
+ "wy" : "7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFp+3lzJYQ/r/L3pbVEXani/WIm9+\n+Q7wv+kkEEsC2457u43mYse5sc+bIvei5YK9RtWB1oh477K4YbEx2KHWZw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 183,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "JxzYnAABQwlrYtTp5MqIWu8vcCPRiv_a-Le1SJgUh1Q",
+ "y" : "ChxulU4yEIQ1tV-jhbD3ZIGmCbkUnMtLArLKR_6OTaU"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5",
+ "wx" : "271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b54898148754",
+ "wy" : "0a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJxzYnAABQwlrYtTp5MqIWu8vcCPR\niv/a+Le1SJgUh1QKHG6VTjIQhDW1X6OFsPdkgaYJuRScy0sCsspH/o5NpQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 184,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "PQvH7Y8J0st920brwe15mrFWOpq4S_UkWHoiCv5JnBI",
+ "y" : "4i3Ds8EDgkpPN42WrbCkCKvxnOfWiqYkT3jLIW-j-N8"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "043d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df",
+ "wx" : "3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12",
+ "wy" : "00e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPQvH7Y8J0st920brwe15mrFWOpq4\nS/UkWHoiCv5JnBLiLcOzwQOCSk83jZatsKQIq/Gc59aKpiRPeMshb6P43w==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 185,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2963333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "psiFreGkxWb5uwENBml0q7KBeX-nASiMchvL0jZjqbc",
+ "y" : "LkJLaQlXFo0ZOmCW_HeisASpx9Rn4Afh8gWEWPmK8xY"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316",
+ "wx" : "00a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b7",
+ "wy" : "2e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpsiFreGkxWb5uwENBml0q7KBeX+n\nASiMchvL0jZjqbcuQktpCVcWjRk6YJb8d6KwBKnH1GfgB+HyBYRY+YrzFg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 186,
+ "comment" : "extreme value for k and s^-1",
+ "msg" : "313233343030",
+ "sig" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29649249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "jTwsLDt2W6gonmrDgSVyolv3XfYth6tzMMO9utnr-lw",
+ "y" : "TGhFRC1mk1sjhXjUOuxU98qhYh0a8kHUYy4LeAxCP10"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "048d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d",
+ "wx" : "008d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c",
+ "wy" : "4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200048d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjTwsLDt2W6gonmrDgSVyolv3XfYt\nh6tzMMO9utnr+lxMaEVELWaTWyOFeNQ67FT3yqFiHRryQdRjLgt4DEI/XQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 187,
+ "comment" : "extreme value for k",
+ "msg" : "313233343030",
+ "sig" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29616a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpY",
+ "y" : "T-NC4v4af5uO5-tKfA-eFivOM1drMV7Oy7ZAaDe_UfU"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+ "wx" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
+ "wy" : "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaxfR8uEsQkf4vOblY6RA8ncDfYEt\n6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9Q==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 188,
+ "comment" : "testing point duplication",
+ "msg" : "313233343030",
+ "sig" : "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 189,
+ "comment" : "testing point duplication",
+ "msg" : "313233343030",
+ "sig" : "44a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpY",
+ "y" : "sBy9HAHlgGVxGBS1g_Bh6dQxzKmUzqExNEm_l8hArgo"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
+ "wx" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
+ "wy" : "00b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaxfR8uEsQkf4vOblY6RA8ncDfYEt\n6zOg9KE5RdiYwpawHL0cAeWAZXEYFLWD8GHp1DHMqZTOoTE0Sb+XyECuCg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 190,
+ "comment" : "testing point duplication",
+ "msg" : "313233343030",
+ "sig" : "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2",
+ "result" : "invalid",
+ "flags" : []
+ },
+ {
+ "tcId" : 191,
+ "comment" : "testing point duplication",
+ "msg" : "313233343030",
+ "sig" : "44a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2",
+ "result" : "invalid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "BKrsc2NXJvIT-4qeZNo7hjLkFJWpRNAEW1IuunJA-tU",
+ "y" : "h9kxV5iqo6W6AXdXh87QXqr3tOCfyB1tGqVG6DZdUl0"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0404aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "wx" : "04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad5",
+ "wy" : "0087d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000404aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBKrsc2NXJvIT+4qeZNo7hjLkFJWp\nRNAEW1IuunJA+tWH2TFXmKqjpboBd1eHztBeqve04J/IHW0apUboNl1SXQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 192,
+ "comment" : "pseudorandom signature",
+ "msg" : "",
+ "sig" : "b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a0177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e2",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 193,
+ "comment" : "pseudorandom signature",
+ "msg" : "4d7367",
+ "sig" : "530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e9",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 194,
+ "comment" : "pseudorandom signature",
+ "msg" : "313233343030",
+ "sig" : "a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b86",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 195,
+ "comment" : "pseudorandom signature",
+ "msg" : "0000000000000000000000000000000000000000",
+ "sig" : "986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb713dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "TzN8z9Z3JqgF5PFgCuKEnfOAfsoRc4Ajn72BaQAAAAA",
+ "y" : "7Z3qEkzIw5ZBZBHpiMMPQn61BK9DoxRs1d9-pgZm1oU"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "044f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
+ "wx" : "4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000",
+ "wy" : "00ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETzN8z9Z3JqgF5PFgCuKEnfOAfsoR\nc4Ajn72BaQAAAADtneoSTMjDlkFkEemIww9CfrUEr0OjFGzV336mBmbWhQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 196,
+ "comment" : "x-coordinate of the public key has many trailing 0's",
+ "msg" : "4d657373616765",
+ "sig" : "d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f19b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 197,
+ "comment" : "x-coordinate of the public key has many trailing 0's",
+ "msg" : "4d657373616765",
+ "sig" : "0fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df55737",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 198,
+ "comment" : "x-coordinate of the public key has many trailing 0's",
+ "msg" : "4d657373616765",
+ "sig" : "bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e3541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb55677",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "PPA9YU2JOc_UmaB4c_rCgWGPBrj_h-gBXD9JcmUASTU",
+ "y" : "hPoXTXkccr8s44gKiWDdKnx6EzioL4Wp5Zzb3oAAAAA"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
+ "wx" : "3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f497265004935",
+ "wy" : "0084fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPPA9YU2JOc/UmaB4c/rCgWGPBrj/\nh+gBXD9JcmUASTWE+hdNeRxyvyzjiAqJYN0qfHoTOKgvhanlnNvegAAAAA==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 199,
+ "comment" : "y-coordinate of the public key has many trailing 0's",
+ "msg" : "4d657373616765",
+ "sig" : "664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a59f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 200,
+ "comment" : "y-coordinate of the public key has many trailing 0's",
+ "msg" : "4d657373616765",
+ "sig" : "4cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b439638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe3",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 201,
+ "comment" : "y-coordinate of the public key has many trailing 0's",
+ "msg" : "4d657373616765",
+ "sig" : "e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b55",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "PPA9YU2JOc_UmaB4c_rCgWGPBrj_h-gBXD9JcmUASTU",
+ "y" : "ewXosYbjjUHTHHf1dp8i1YOF7MhX0HpWGmMkIX____8"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
+ "wx" : "3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f497265004935",
+ "wy" : "7b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPPA9YU2JOc/UmaB4c/rCgWGPBrj/\nh+gBXD9JcmUASTV7BeixhuONQdMcd/V2nyLVg4XsyFfQelYaYyQhf////w==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 202,
+ "comment" : "y-coordinate of the public key has many trailing 1's",
+ "msg" : "4d657373616765",
+ "sig" : "1158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf3466830228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f285519",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 203,
+ "comment" : "y-coordinate of the public key has many trailing 1's",
+ "msg" : "4d657373616765",
+ "sig" : "b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d3e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a1251336",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 204,
+ "comment" : "y-coordinate of the public key has many trailing 1's",
+ "msg" : "4d657373616765",
+ "sig" : "b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "KCnDH6ouQA40TtlLyj_NBUWVbrz-itD236X_jv____8",
+ "y" : "oBqvrwAOUlhYVa-nZ2reKEETCZBS31fn6zvTfr65Ii4"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "042829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
+ "wx" : "2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffff",
+ "wy" : "00a01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKCnDH6ouQA40TtlLyj/NBUWVbrz+\nitD236X/jv////+gGq+vAA5SWFhVr6dnat4oQRMJkFLfV+frO9N+vrkiLg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 205,
+ "comment" : "x-coordinate of the public key has many trailing 1's",
+ "msg" : "4d657373616765",
+ "sig" : "d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b43dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd139929",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 206,
+ "comment" : "x-coordinate of the public key has many trailing 1's",
+ "msg" : "4d657373616765",
+ "sig" : "5eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af782c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb5",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 207,
+ "comment" : "x-coordinate of the public key has many trailing 1's",
+ "msg" : "4d657373616765",
+ "sig" : "96843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "____-UgIHmoEWN2PnnOPJmX_kFmtaqwHCDGMTKmnpPU",
+ "y" : "Woq8ui3ahHQxHuVBSblzyuDA-4lVetC_eOZSmhZjvXM"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
+ "wx" : "00fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f5",
+ "wy" : "5a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE////+UgIHmoEWN2PnnOPJmX/kFmt\naqwHCDGMTKmnpPVairy6LdqEdDEe5UFJuXPK4MD7iVV60L945lKaFmO9cw==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 208,
+ "comment" : "x-coordinate of the public key is large",
+ "msg" : "4d657373616765",
+ "sig" : "766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f6402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 209,
+ "comment" : "x-coordinate of the public key is large",
+ "msg" : "4d657373616765",
+ "sig" : "c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dba",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 210,
+ "comment" : "x-coordinate of the public key is large",
+ "msg" : "4d657373616765",
+ "sig" : "d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "AAAAA_oV-WOUnV8DpvXH-G-eABXusjrrv_EXOTe6dI4",
+ "y" : "EJmHIHDo6HxVX6E2Wcyl1_rc_LACPqiJVIykivK6fnE"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "0400000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
+ "wx" : "03fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e",
+ "wy" : "1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000400000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAAAAA/oV+WOUnV8DpvXH+G+eABXu\nsjrrv/EXOTe6dI4QmYcgcOjofFVfoTZZzKXX+tz8sAI+qIlUjKSK8rp+cQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 211,
+ "comment" : "x-coordinate of the public key is small",
+ "msg" : "4d657373616765",
+ "sig" : "b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb3",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 212,
+ "comment" : "x-coordinate of the public key is small",
+ "msg" : "4d657373616765",
+ "sig" : "6b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f75939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 213,
+ "comment" : "x-coordinate of the public key is small",
+ "msg" : "4d657373616765",
+ "sig" : "efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "vLspFMefBF6qbsu8YSgWs75dLWeWcH2BJen4UcGK8BU",
+ "y" : "AAAAABNSu0oPoupMzrmrY91oSt5aESe88wCmmKcZO8I"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
+ "wx" : "00bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015",
+ "wy" : "1352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvLspFMefBF6qbsu8YSgWs75dLWeW\ncH2BJen4UcGK8BUAAAAAE1K7Sg+i6kzOuatj3WhK3loRJ7zzAKaYpxk7wg==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 214,
+ "comment" : "y-coordinate of the public key is small",
+ "msg" : "4d657373616765",
+ "sig" : "31230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beff",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 215,
+ "comment" : "y-coordinate of the public key is small",
+ "msg" : "4d657373616765",
+ "sig" : "caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 216,
+ "comment" : "y-coordinate of the public key is small",
+ "msg" : "4d657373616765",
+ "sig" : "7e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859459450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aa",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ },
+ {
+ "jwk" : {
+ "crv" : "P-256",
+ "kid" : "none",
+ "kty" : "EC",
+ "x" : "vLspFMefBF6qbsu8YSgWs75dLWeWcH2BJen4UcGK8BU",
+ "y" : "_____uytRLbwXRWzMUZUnCKXtSKl7thDDP9ZZ1jmxD0"
+ },
+ "key" : {
+ "curve" : "secp256r1",
+ "keySize" : 256,
+ "type" : "EcPublicKey",
+ "uncompressed" : "04bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
+ "wx" : "00bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015",
+ "wy" : "00fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d"
+ },
+ "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d",
+ "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvLspFMefBF6qbsu8YSgWs75dLWeW\ncH2BJen4UcGK8BX////+7K1EtvBdFbMxRlScIpe1IqXu2EMM/1lnWObEPQ==\n-----END PUBLIC KEY-----",
+ "sha" : "SHA-256",
+ "type" : "EcdsaP1363Verify",
+ "tests" : [
+ {
+ "tcId" : 217,
+ "comment" : "y-coordinate of the public key is large",
+ "msg" : "4d657373616765",
+ "sig" : "d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35689c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 218,
+ "comment" : "y-coordinate of the public key is large",
+ "msg" : "4d657373616765",
+ "sig" : "341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b3472b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469",
+ "result" : "valid",
+ "flags" : []
+ },
+ {
+ "tcId" : 219,
+ "comment" : "y-coordinate of the public key is large",
+ "msg" : "4d657373616765",
+ "sig" : "70bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9",
+ "result" : "valid",
+ "flags" : []
+ }
+ ]
+ }
+ ]
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/ERC165.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/ERC165.test.js
new file mode 100644
index 000000000..8117c695e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/ERC165.test.js
@@ -0,0 +1,18 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { shouldSupportInterfaces } = require('./SupportsInterface.behavior');
+
+async function fixture() {
+ return {
+ mock: await ethers.deployContract('$ERC165'),
+ };
+}
+
+describe('ERC165', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ shouldSupportInterfaces();
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/ERC165Checker.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/ERC165Checker.test.js
new file mode 100644
index 000000000..1bbe8a571
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/ERC165Checker.test.js
@@ -0,0 +1,245 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const DUMMY_ID = '0xdeadbeef';
+const DUMMY_ID_2 = '0xcafebabe';
+const DUMMY_ID_3 = '0xdecafbad';
+const DUMMY_UNSUPPORTED_ID = '0xbaddcafe';
+const DUMMY_UNSUPPORTED_ID_2 = '0xbaadcafe';
+const DUMMY_ACCOUNT = '0x1111111111111111111111111111111111111111';
+
+async function fixture() {
+ return { mock: await ethers.deployContract('$ERC165Checker') };
+}
+
+describe('ERC165Checker', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('ERC165 missing return data', function () {
+ before(async function () {
+ this.target = await ethers.deployContract('ERC165MissingData');
+ });
+
+ it('does not support ERC165', async function () {
+ expect(await this.mock.$supportsERC165(this.target)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsInterface', async function () {
+ expect(await this.mock.$supportsInterface(this.target, DUMMY_ID)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(this.target, [DUMMY_ID])).to.be.false;
+ });
+
+ it('does not support mock interface via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(this.target, [DUMMY_ID])).to.deep.equal([false]);
+ });
+
+ it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(this.target, DUMMY_ID)).to.be.false;
+ });
+ });
+
+ describe('ERC165 malicious return data', function () {
+ beforeEach(async function () {
+ this.target = await ethers.deployContract('ERC165MaliciousData');
+ });
+
+ it('does not support ERC165', async function () {
+ expect(await this.mock.$supportsERC165(this.target)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsInterface', async function () {
+ expect(await this.mock.$supportsInterface(this.target, DUMMY_ID)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(this.target, [DUMMY_ID])).to.be.false;
+ });
+
+ it('does not support mock interface via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(this.target, [DUMMY_ID])).to.deep.equal([false]);
+ });
+
+ it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(this.target, DUMMY_ID)).to.be.true;
+ });
+ });
+
+ describe('ERC165 not supported', function () {
+ beforeEach(async function () {
+ this.target = await ethers.deployContract('ERC165NotSupported');
+ });
+
+ it('does not support ERC165', async function () {
+ expect(await this.mock.$supportsERC165(this.target)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsInterface', async function () {
+ expect(await this.mock.$supportsInterface(this.target, DUMMY_ID)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(this.target, [DUMMY_ID])).to.be.false;
+ });
+
+ it('does not support mock interface via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(this.target, [DUMMY_ID])).to.deep.equal([false]);
+ });
+
+ it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(this.target, DUMMY_ID)).to.be.false;
+ });
+ });
+
+ describe('ERC165 supported', function () {
+ beforeEach(async function () {
+ this.target = await ethers.deployContract('ERC165InterfacesSupported', [[]]);
+ });
+
+ it('supports ERC165', async function () {
+ expect(await this.mock.$supportsERC165(this.target)).to.be.true;
+ });
+
+ it('does not support mock interface via supportsInterface', async function () {
+ expect(await this.mock.$supportsInterface(this.target, DUMMY_ID)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(this.target, [DUMMY_ID])).to.be.false;
+ });
+
+ it('does not support mock interface via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(this.target, [DUMMY_ID])).to.deep.equal([false]);
+ });
+
+ it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(this.target, DUMMY_ID)).to.be.false;
+ });
+ });
+
+ describe('ERC165 and single interface supported', function () {
+ beforeEach(async function () {
+ this.target = await ethers.deployContract('ERC165InterfacesSupported', [[DUMMY_ID]]);
+ });
+
+ it('supports ERC165', async function () {
+ expect(await this.mock.$supportsERC165(this.target)).to.be.true;
+ });
+
+ it('supports mock interface via supportsInterface', async function () {
+ expect(await this.mock.$supportsInterface(this.target, DUMMY_ID)).to.be.true;
+ });
+
+ it('supports mock interface via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(this.target, [DUMMY_ID])).to.be.true;
+ });
+
+ it('supports mock interface via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(this.target, [DUMMY_ID])).to.deep.equal([true]);
+ });
+
+ it('supports mock interface via supportsERC165InterfaceUnchecked', async function () {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(this.target, DUMMY_ID)).to.be.true;
+ });
+ });
+
+ describe('ERC165 and many interfaces supported', function () {
+ const supportedInterfaces = [DUMMY_ID, DUMMY_ID_2, DUMMY_ID_3];
+ beforeEach(async function () {
+ this.target = await ethers.deployContract('ERC165InterfacesSupported', [supportedInterfaces]);
+ });
+
+ it('supports ERC165', async function () {
+ expect(await this.mock.$supportsERC165(this.target)).to.be.true;
+ });
+
+ it('supports each interfaceId via supportsInterface', async function () {
+ for (const interfaceId of supportedInterfaces) {
+ expect(await this.mock.$supportsInterface(this.target, interfaceId)).to.be.true;
+ }
+ });
+
+ it('supports all interfaceIds via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(this.target, supportedInterfaces)).to.be.true;
+ });
+
+ it('supports none of the interfaces queried via supportsAllInterfaces', async function () {
+ const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2];
+
+ expect(await this.mock.$supportsAllInterfaces(this.target, interfaceIdsToTest)).to.be.false;
+ });
+
+ it('supports not all of the interfaces queried via supportsAllInterfaces', async function () {
+ const interfaceIdsToTest = [...supportedInterfaces, DUMMY_UNSUPPORTED_ID];
+ expect(await this.mock.$supportsAllInterfaces(this.target, interfaceIdsToTest)).to.be.false;
+ });
+
+ it('supports all interfaceIds via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(this.target, supportedInterfaces)).to.deep.equal(
+ supportedInterfaces.map(i => supportedInterfaces.includes(i)),
+ );
+ });
+
+ it('supports none of the interfaces queried via getSupportedInterfaces', async function () {
+ const interfaceIdsToTest = [DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2];
+
+ expect(await this.mock.$getSupportedInterfaces(this.target, interfaceIdsToTest)).to.deep.equal(
+ interfaceIdsToTest.map(i => supportedInterfaces.includes(i)),
+ );
+ });
+
+ it('supports not all of the interfaces queried via getSupportedInterfaces', async function () {
+ const interfaceIdsToTest = [...supportedInterfaces, DUMMY_UNSUPPORTED_ID];
+
+ expect(await this.mock.$getSupportedInterfaces(this.target, interfaceIdsToTest)).to.deep.equal(
+ interfaceIdsToTest.map(i => supportedInterfaces.includes(i)),
+ );
+ });
+
+ it('supports each interfaceId via supportsERC165InterfaceUnchecked', async function () {
+ for (const interfaceId of supportedInterfaces) {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(this.target, interfaceId)).to.be.true;
+ }
+ });
+ });
+
+ describe('account address does not support ERC165', function () {
+ it('does not support ERC165', async function () {
+ expect(await this.mock.$supportsERC165(DUMMY_ACCOUNT)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsInterface', async function () {
+ expect(await this.mock.$supportsInterface(DUMMY_ACCOUNT, DUMMY_ID)).to.be.false;
+ });
+
+ it('does not support mock interface via supportsAllInterfaces', async function () {
+ expect(await this.mock.$supportsAllInterfaces(DUMMY_ACCOUNT, [DUMMY_ID])).to.be.false;
+ });
+
+ it('does not support mock interface via getSupportedInterfaces', async function () {
+ expect(await this.mock.$getSupportedInterfaces(DUMMY_ACCOUNT, [DUMMY_ID])).to.deep.equal([false]);
+ });
+
+ it('does not support mock interface via supportsERC165InterfaceUnchecked', async function () {
+ expect(await this.mock.$supportsERC165InterfaceUnchecked(DUMMY_ACCOUNT, DUMMY_ID)).to.be.false;
+ });
+ });
+
+ it('Return bomb resistance', async function () {
+ this.target = await ethers.deployContract('ERC165ReturnBombMock');
+
+ const { gasUsed: gasUsed1 } = await this.mock.$supportsInterface.send(this.target, DUMMY_ID).then(tx => tx.wait());
+ expect(gasUsed1).to.be.lessThan(120_000n); // 3*30k + 21k + some margin
+
+ const { gasUsed: gasUsed2 } = await this.mock.$getSupportedInterfaces
+ .send(this.target, [DUMMY_ID, DUMMY_ID_2, DUMMY_ID_3, DUMMY_UNSUPPORTED_ID, DUMMY_UNSUPPORTED_ID_2])
+ .then(tx => tx.wait());
+
+ expect(gasUsed2).to.be.lessThan(250_000n); // (2+5)*30k + 21k + some margin
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/SupportsInterface.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/SupportsInterface.behavior.js
new file mode 100644
index 000000000..8a7bc4b5e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/introspection/SupportsInterface.behavior.js
@@ -0,0 +1,145 @@
+const { expect } = require('chai');
+const { interfaceId } = require('../../helpers/methods');
+const { mapValues } = require('../../helpers/iterate');
+
+const INVALID_ID = '0xffffffff';
+const SIGNATURES = {
+ ERC165: ['supportsInterface(bytes4)'],
+ ERC721: [
+ 'balanceOf(address)',
+ 'ownerOf(uint256)',
+ 'approve(address,uint256)',
+ 'getApproved(uint256)',
+ 'setApprovalForAll(address,bool)',
+ 'isApprovedForAll(address,address)',
+ 'transferFrom(address,address,uint256)',
+ 'safeTransferFrom(address,address,uint256)',
+ 'safeTransferFrom(address,address,uint256,bytes)',
+ ],
+ ERC721Enumerable: ['totalSupply()', 'tokenOfOwnerByIndex(address,uint256)', 'tokenByIndex(uint256)'],
+ ERC721Metadata: ['name()', 'symbol()', 'tokenURI(uint256)'],
+ ERC1155: [
+ 'balanceOf(address,uint256)',
+ 'balanceOfBatch(address[],uint256[])',
+ 'setApprovalForAll(address,bool)',
+ 'isApprovedForAll(address,address)',
+ 'safeTransferFrom(address,address,uint256,uint256,bytes)',
+ 'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)',
+ ],
+ ERC1155MetadataURI: ['uri(uint256)'],
+ ERC1155Receiver: [
+ 'onERC1155Received(address,address,uint256,uint256,bytes)',
+ 'onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)',
+ ],
+ ERC1363: [
+ 'transferAndCall(address,uint256)',
+ 'transferAndCall(address,uint256,bytes)',
+ 'transferFromAndCall(address,address,uint256)',
+ 'transferFromAndCall(address,address,uint256,bytes)',
+ 'approveAndCall(address,uint256)',
+ 'approveAndCall(address,uint256,bytes)',
+ ],
+ AccessControl: [
+ 'hasRole(bytes32,address)',
+ 'getRoleAdmin(bytes32)',
+ 'grantRole(bytes32,address)',
+ 'revokeRole(bytes32,address)',
+ 'renounceRole(bytes32,address)',
+ ],
+ AccessControlEnumerable: ['getRoleMember(bytes32,uint256)', 'getRoleMemberCount(bytes32)'],
+ AccessControlDefaultAdminRules: [
+ 'defaultAdminDelay()',
+ 'pendingDefaultAdminDelay()',
+ 'defaultAdmin()',
+ 'pendingDefaultAdmin()',
+ 'defaultAdminDelayIncreaseWait()',
+ 'changeDefaultAdminDelay(uint48)',
+ 'rollbackDefaultAdminDelay()',
+ 'beginDefaultAdminTransfer(address)',
+ 'acceptDefaultAdminTransfer()',
+ 'cancelDefaultAdminTransfer()',
+ ],
+ Governor: [
+ 'name()',
+ 'version()',
+ 'COUNTING_MODE()',
+ 'hashProposal(address[],uint256[],bytes[],bytes32)',
+ 'state(uint256)',
+ 'proposalThreshold()',
+ 'proposalSnapshot(uint256)',
+ 'proposalDeadline(uint256)',
+ 'proposalProposer(uint256)',
+ 'proposalEta(uint256)',
+ 'proposalNeedsQueuing(uint256)',
+ 'votingDelay()',
+ 'votingPeriod()',
+ 'quorum(uint256)',
+ 'getVotes(address,uint256)',
+ 'getVotesWithParams(address,uint256,bytes)',
+ 'hasVoted(uint256,address)',
+ 'propose(address[],uint256[],bytes[],string)',
+ 'queue(address[],uint256[],bytes[],bytes32)',
+ 'execute(address[],uint256[],bytes[],bytes32)',
+ 'cancel(address[],uint256[],bytes[],bytes32)',
+ 'castVote(uint256,uint8)',
+ 'castVoteWithReason(uint256,uint8,string)',
+ 'castVoteWithReasonAndParams(uint256,uint8,string,bytes)',
+ 'castVoteBySig(uint256,uint8,address,bytes)',
+ 'castVoteWithReasonAndParamsBySig(uint256,uint8,address,string,bytes,bytes)',
+ ],
+ ERC2981: ['royaltyInfo(uint256,uint256)'],
+};
+
+const INTERFACE_IDS = mapValues(SIGNATURES, interfaceId);
+
+function shouldSupportInterfaces(interfaces = []) {
+ interfaces.unshift('ERC165');
+
+ describe('ERC165', function () {
+ beforeEach(function () {
+ this.contractUnderTest = this.mock || this.token;
+ });
+
+ describe('when the interfaceId is supported', function () {
+ it('uses less than 30k gas', async function () {
+ for (const k of interfaces) {
+ const interfaceId = INTERFACE_IDS[k] ?? k;
+ expect(await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).to.lte(30_000n);
+ }
+ });
+
+ it('returns true', async function () {
+ for (const k of interfaces) {
+ const interfaceId = INTERFACE_IDS[k] ?? k;
+ expect(await this.contractUnderTest.supportsInterface(interfaceId), `does not support ${k}`).to.be.true;
+ }
+ });
+ });
+
+ describe('when the interfaceId is not supported', function () {
+ it('uses less than 30k', async function () {
+ expect(await this.contractUnderTest.supportsInterface.estimateGas(INVALID_ID)).to.lte(30_000n);
+ });
+
+ it('returns false', async function () {
+ expect(await this.contractUnderTest.supportsInterface(INVALID_ID), `supports ${INVALID_ID}`).to.be.false;
+ });
+ });
+
+ it('all interface functions are in ABI', async function () {
+ for (const k of interfaces) {
+ // skip interfaces for which we don't have a function list
+ if (SIGNATURES[k] === undefined) continue;
+
+ // Check the presence of each function in the contract's interface
+ for (const fnSig of SIGNATURES[k]) {
+ expect(this.contractUnderTest.interface.hasFunction(fnSig), `did not find ${fnSig}`).to.be.true;
+ }
+ }
+ });
+ });
+}
+
+module.exports = {
+ shouldSupportInterfaces,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/Math.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/Math.t.sol
new file mode 100644
index 000000000..3d4932eea
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/Math.t.sol
@@ -0,0 +1,311 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test, stdError} from "forge-std/Test.sol";
+
+import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
+
+contract MathTest is Test {
+ function testSymbolicTernary(bool f, uint256 a, uint256 b) public {
+ assertEq(Math.ternary(f, a, b), f ? a : b);
+ }
+
+ // MIN & MAX
+ function testSymbolicMinMax(uint256 a, uint256 b) public {
+ assertEq(Math.min(a, b), a < b ? a : b);
+ assertEq(Math.max(a, b), a > b ? a : b);
+ }
+
+ // CEILDIV
+ function testCeilDiv(uint256 a, uint256 b) public {
+ vm.assume(b > 0);
+
+ uint256 result = Math.ceilDiv(a, b);
+
+ if (result == 0) {
+ assertEq(a, 0);
+ } else {
+ uint256 expect = a / b;
+ if (expect * b < a) {
+ expect += 1;
+ }
+ assertEq(result, expect);
+ }
+ }
+
+ // SQRT
+ function testSqrt(uint256 input, uint8 r) public {
+ Math.Rounding rounding = _asRounding(r);
+
+ uint256 result = Math.sqrt(input, rounding);
+
+ // square of result is bigger than input
+ if (_squareBigger(result, input)) {
+ assertTrue(Math.unsignedRoundsUp(rounding));
+ assertTrue(_squareSmaller(result - 1, input));
+ }
+ // square of result is smaller than input
+ else if (_squareSmaller(result, input)) {
+ assertFalse(Math.unsignedRoundsUp(rounding));
+ assertTrue(_squareBigger(result + 1, input));
+ }
+ // input is perfect square
+ else {
+ assertEq(result * result, input);
+ }
+ }
+
+ function _squareBigger(uint256 value, uint256 ref) private pure returns (bool) {
+ (bool noOverflow, uint256 square) = Math.tryMul(value, value);
+ return !noOverflow || square > ref;
+ }
+
+ function _squareSmaller(uint256 value, uint256 ref) private pure returns (bool) {
+ return value * value < ref;
+ }
+
+ // INV
+ function testInvMod(uint256 value, uint256 p) public {
+ _testInvMod(value, p, true);
+ }
+
+ function testInvMod2(uint256 seed) public {
+ uint256 p = 2; // prime
+ _testInvMod(bound(seed, 1, p - 1), p, false);
+ }
+
+ function testInvMod17(uint256 seed) public {
+ uint256 p = 17; // prime
+ _testInvMod(bound(seed, 1, p - 1), p, false);
+ }
+
+ function testInvMod65537(uint256 seed) public {
+ uint256 p = 65537; // prime
+ _testInvMod(bound(seed, 1, p - 1), p, false);
+ }
+
+ function testInvModP256(uint256 seed) public {
+ uint256 p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff; // prime
+ _testInvMod(bound(seed, 1, p - 1), p, false);
+ }
+
+ function _testInvMod(uint256 value, uint256 p, bool allowZero) private {
+ uint256 inverse = Math.invMod(value, p);
+ if (inverse != 0) {
+ assertEq(mulmod(value, inverse, p), 1);
+ assertLt(inverse, p);
+ } else {
+ assertTrue(allowZero);
+ }
+ }
+
+ // LOG2
+ function testLog2(uint256 input, uint8 r) public {
+ Math.Rounding rounding = _asRounding(r);
+
+ uint256 result = Math.log2(input, rounding);
+
+ if (input == 0) {
+ assertEq(result, 0);
+ } else if (_powerOf2Bigger(result, input)) {
+ assertTrue(Math.unsignedRoundsUp(rounding));
+ assertTrue(_powerOf2Smaller(result - 1, input));
+ } else if (_powerOf2Smaller(result, input)) {
+ assertFalse(Math.unsignedRoundsUp(rounding));
+ assertTrue(_powerOf2Bigger(result + 1, input));
+ } else {
+ assertEq(2 ** result, input);
+ }
+ }
+
+ function _powerOf2Bigger(uint256 value, uint256 ref) private pure returns (bool) {
+ return value >= 256 || 2 ** value > ref; // 2**256 overflows uint256
+ }
+
+ function _powerOf2Smaller(uint256 value, uint256 ref) private pure returns (bool) {
+ return 2 ** value < ref;
+ }
+
+ // LOG10
+ function testLog10(uint256 input, uint8 r) public {
+ Math.Rounding rounding = _asRounding(r);
+
+ uint256 result = Math.log10(input, rounding);
+
+ if (input == 0) {
+ assertEq(result, 0);
+ } else if (_powerOf10Bigger(result, input)) {
+ assertTrue(Math.unsignedRoundsUp(rounding));
+ assertTrue(_powerOf10Smaller(result - 1, input));
+ } else if (_powerOf10Smaller(result, input)) {
+ assertFalse(Math.unsignedRoundsUp(rounding));
+ assertTrue(_powerOf10Bigger(result + 1, input));
+ } else {
+ assertEq(10 ** result, input);
+ }
+ }
+
+ function _powerOf10Bigger(uint256 value, uint256 ref) private pure returns (bool) {
+ return value >= 78 || 10 ** value > ref; // 10**78 overflows uint256
+ }
+
+ function _powerOf10Smaller(uint256 value, uint256 ref) private pure returns (bool) {
+ return 10 ** value < ref;
+ }
+
+ // LOG256
+ function testLog256(uint256 input, uint8 r) public {
+ Math.Rounding rounding = _asRounding(r);
+
+ uint256 result = Math.log256(input, rounding);
+
+ if (input == 0) {
+ assertEq(result, 0);
+ } else if (_powerOf256Bigger(result, input)) {
+ assertTrue(Math.unsignedRoundsUp(rounding));
+ assertTrue(_powerOf256Smaller(result - 1, input));
+ } else if (_powerOf256Smaller(result, input)) {
+ assertFalse(Math.unsignedRoundsUp(rounding));
+ assertTrue(_powerOf256Bigger(result + 1, input));
+ } else {
+ assertEq(256 ** result, input);
+ }
+ }
+
+ function _powerOf256Bigger(uint256 value, uint256 ref) private pure returns (bool) {
+ return value >= 32 || 256 ** value > ref; // 256**32 overflows uint256
+ }
+
+ function _powerOf256Smaller(uint256 value, uint256 ref) private pure returns (bool) {
+ return 256 ** value < ref;
+ }
+
+ // MULDIV
+ function testMulDiv(uint256 x, uint256 y, uint256 d) public {
+ // Full precision for x * y
+ (uint256 xyHi, uint256 xyLo) = _mulHighLow(x, y);
+
+ // Assume result won't overflow (see {testMulDivDomain})
+ // This also checks that `d` is positive
+ vm.assume(xyHi < d);
+
+ // Perform muldiv
+ uint256 q = Math.mulDiv(x, y, d);
+
+ // Full precision for q * d
+ (uint256 qdHi, uint256 qdLo) = _mulHighLow(q, d);
+ // Add remainder of x * y / d (computed as rem = (x * y % d))
+ (uint256 qdRemLo, uint256 c) = _addCarry(qdLo, mulmod(x, y, d));
+ uint256 qdRemHi = qdHi + c;
+
+ // Full precision check that x * y = q * d + rem
+ assertEq(xyHi, qdRemHi);
+ assertEq(xyLo, qdRemLo);
+ }
+
+ function testMulDivDomain(uint256 x, uint256 y, uint256 d) public {
+ (uint256 xyHi, ) = _mulHighLow(x, y);
+
+ // Violate {testMulDiv} assumption (covers d is 0 and result overflow)
+ vm.assume(xyHi >= d);
+
+ // we are outside the scope of {testMulDiv}, we expect muldiv to revert
+ vm.expectRevert(d == 0 ? stdError.divisionError : stdError.arithmeticError);
+ Math.mulDiv(x, y, d);
+ }
+
+ // MOD EXP
+ function testModExp(uint256 b, uint256 e, uint256 m) public {
+ if (m == 0) {
+ vm.expectRevert(stdError.divisionError);
+ }
+ uint256 result = Math.modExp(b, e, m);
+ assertLt(result, m);
+ assertEq(result, _nativeModExp(b, e, m));
+ }
+
+ function testTryModExp(uint256 b, uint256 e, uint256 m) public {
+ (bool success, uint256 result) = Math.tryModExp(b, e, m);
+ assertEq(success, m != 0);
+ if (success) {
+ assertLt(result, m);
+ assertEq(result, _nativeModExp(b, e, m));
+ } else {
+ assertEq(result, 0);
+ }
+ }
+
+ function testModExpMemory(uint256 b, uint256 e, uint256 m) public {
+ if (m == 0) {
+ vm.expectRevert(stdError.divisionError);
+ }
+ bytes memory result = Math.modExp(abi.encodePacked(b), abi.encodePacked(e), abi.encodePacked(m));
+ assertEq(result.length, 0x20);
+ uint256 res = abi.decode(result, (uint256));
+ assertLt(res, m);
+ assertEq(res, _nativeModExp(b, e, m));
+ }
+
+ function testTryModExpMemory(uint256 b, uint256 e, uint256 m) public {
+ (bool success, bytes memory result) = Math.tryModExp(
+ abi.encodePacked(b),
+ abi.encodePacked(e),
+ abi.encodePacked(m)
+ );
+ if (success) {
+ assertEq(result.length, 0x20); // m is a uint256, so abi.encodePacked(m).length is 0x20
+ uint256 res = abi.decode(result, (uint256));
+ assertLt(res, m);
+ assertEq(res, _nativeModExp(b, e, m));
+ } else {
+ assertEq(result.length, 0);
+ }
+ }
+
+ function _nativeModExp(uint256 b, uint256 e, uint256 m) private pure returns (uint256) {
+ if (m == 1) return 0;
+ uint256 r = 1;
+ while (e > 0) {
+ if (e % 2 > 0) {
+ r = mulmod(r, b, m);
+ }
+ b = mulmod(b, b, m);
+ e >>= 1;
+ }
+ return r;
+ }
+
+ // Helpers
+ function _asRounding(uint8 r) private pure returns (Math.Rounding) {
+ vm.assume(r < uint8(type(Math.Rounding).max));
+ return Math.Rounding(r);
+ }
+
+ function _mulHighLow(uint256 x, uint256 y) private pure returns (uint256 high, uint256 low) {
+ (uint256 x0, uint256 x1) = (x & type(uint128).max, x >> 128);
+ (uint256 y0, uint256 y1) = (y & type(uint128).max, y >> 128);
+
+ // Karatsuba algorithm
+ // https://en.wikipedia.org/wiki/Karatsuba_algorithm
+ uint256 z2 = x1 * y1;
+ uint256 z1a = x1 * y0;
+ uint256 z1b = x0 * y1;
+ uint256 z0 = x0 * y0;
+
+ uint256 carry = ((z1a & type(uint128).max) + (z1b & type(uint128).max) + (z0 >> 128)) >> 128;
+
+ high = z2 + (z1a >> 128) + (z1b >> 128) + carry;
+
+ unchecked {
+ low = x * y;
+ }
+ }
+
+ function _addCarry(uint256 x, uint256 y) private pure returns (uint256 res, uint256 carry) {
+ unchecked {
+ res = x + y;
+ }
+ carry = res < x ? 1 : 0;
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/Math.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/Math.test.js
new file mode 100644
index 000000000..f38f2f318
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/Math.test.js
@@ -0,0 +1,562 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { Rounding } = require('../../helpers/enums');
+const { min, max, modExp } = require('../../helpers/math');
+const { generators } = require('../../helpers/random');
+const { product, range } = require('../../helpers/iterate');
+
+const RoundingDown = [Rounding.Floor, Rounding.Trunc];
+const RoundingUp = [Rounding.Ceil, Rounding.Expand];
+
+const bytes = (value, width = undefined) => ethers.Typed.bytes(ethers.toBeHex(value, width));
+const uint256 = value => ethers.Typed.uint256(value);
+bytes.zero = '0x';
+uint256.zero = 0n;
+
+async function testCommutative(fn, lhs, rhs, expected, ...extra) {
+ expect(await fn(lhs, rhs, ...extra)).to.deep.equal(expected);
+ expect(await fn(rhs, lhs, ...extra)).to.deep.equal(expected);
+}
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Math');
+
+ // disambiguation, we use the version with explicit rounding
+ mock.$mulDiv = mock['$mulDiv(uint256,uint256,uint256,uint8)'];
+ mock.$sqrt = mock['$sqrt(uint256,uint8)'];
+ mock.$log2 = mock['$log2(uint256,uint8)'];
+ mock.$log10 = mock['$log10(uint256,uint8)'];
+ mock.$log256 = mock['$log256(uint256,uint8)'];
+
+ return { mock };
+}
+
+describe('Math', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('tryAdd', function () {
+ it('adds correctly', async function () {
+ const a = 5678n;
+ const b = 1234n;
+ await testCommutative(this.mock.$tryAdd, a, b, [true, a + b]);
+ });
+
+ it('reverts on addition overflow', async function () {
+ const a = ethers.MaxUint256;
+ const b = 1n;
+ await testCommutative(this.mock.$tryAdd, a, b, [false, 0n]);
+ });
+ });
+
+ describe('trySub', function () {
+ it('subtracts correctly', async function () {
+ const a = 5678n;
+ const b = 1234n;
+ expect(await this.mock.$trySub(a, b)).to.deep.equal([true, a - b]);
+ });
+
+ it('reverts if subtraction result would be negative', async function () {
+ const a = 1234n;
+ const b = 5678n;
+ expect(await this.mock.$trySub(a, b)).to.deep.equal([false, 0n]);
+ });
+ });
+
+ describe('tryMul', function () {
+ it('multiplies correctly', async function () {
+ const a = 1234n;
+ const b = 5678n;
+ await testCommutative(this.mock.$tryMul, a, b, [true, a * b]);
+ });
+
+ it('multiplies by zero correctly', async function () {
+ const a = 0n;
+ const b = 5678n;
+ await testCommutative(this.mock.$tryMul, a, b, [true, a * b]);
+ });
+
+ it('reverts on multiplication overflow', async function () {
+ const a = ethers.MaxUint256;
+ const b = 2n;
+ await testCommutative(this.mock.$tryMul, a, b, [false, 0n]);
+ });
+ });
+
+ describe('tryDiv', function () {
+ it('divides correctly', async function () {
+ const a = 5678n;
+ const b = 5678n;
+ expect(await this.mock.$tryDiv(a, b)).to.deep.equal([true, a / b]);
+ });
+
+ it('divides zero correctly', async function () {
+ const a = 0n;
+ const b = 5678n;
+ expect(await this.mock.$tryDiv(a, b)).to.deep.equal([true, a / b]);
+ });
+
+ it('returns complete number result on non-even division', async function () {
+ const a = 7000n;
+ const b = 5678n;
+ expect(await this.mock.$tryDiv(a, b)).to.deep.equal([true, a / b]);
+ });
+
+ it('reverts on division by zero', async function () {
+ const a = 5678n;
+ const b = 0n;
+ expect(await this.mock.$tryDiv(a, b)).to.deep.equal([false, 0n]);
+ });
+ });
+
+ describe('tryMod', function () {
+ describe('modulos correctly', function () {
+ it('when the dividend is smaller than the divisor', async function () {
+ const a = 284n;
+ const b = 5678n;
+ expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]);
+ });
+
+ it('when the dividend is equal to the divisor', async function () {
+ const a = 5678n;
+ const b = 5678n;
+ expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]);
+ });
+
+ it('when the dividend is larger than the divisor', async function () {
+ const a = 7000n;
+ const b = 5678n;
+ expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]);
+ });
+
+ it('when the dividend is a multiple of the divisor', async function () {
+ const a = 17034n; // 17034 == 5678 * 3
+ const b = 5678n;
+ expect(await this.mock.$tryMod(a, b)).to.deep.equal([true, a % b]);
+ });
+ });
+
+ it('reverts with a 0 divisor', async function () {
+ const a = 5678n;
+ const b = 0n;
+ expect(await this.mock.$tryMod(a, b)).to.deep.equal([false, 0n]);
+ });
+ });
+
+ describe('max', function () {
+ it('is correctly detected in both position', async function () {
+ await testCommutative(this.mock.$max, 1234n, 5678n, max(1234n, 5678n));
+ });
+ });
+
+ describe('min', function () {
+ it('is correctly detected in both position', async function () {
+ await testCommutative(this.mock.$min, 1234n, 5678n, min(1234n, 5678n));
+ });
+ });
+
+ describe('average', function () {
+ it('is correctly calculated with two odd numbers', async function () {
+ const a = 57417n;
+ const b = 95431n;
+ expect(await this.mock.$average(a, b)).to.equal((a + b) / 2n);
+ });
+
+ it('is correctly calculated with two even numbers', async function () {
+ const a = 42304n;
+ const b = 84346n;
+ expect(await this.mock.$average(a, b)).to.equal((a + b) / 2n);
+ });
+
+ it('is correctly calculated with one even and one odd number', async function () {
+ const a = 57417n;
+ const b = 84346n;
+ expect(await this.mock.$average(a, b)).to.equal((a + b) / 2n);
+ });
+
+ it('is correctly calculated with two max uint256 numbers', async function () {
+ const a = ethers.MaxUint256;
+ expect(await this.mock.$average(a, a)).to.equal(a);
+ });
+ });
+
+ describe('ceilDiv', function () {
+ it('reverts on zero division', async function () {
+ const a = 2n;
+ const b = 0n;
+ // It's unspecified because it's a low level 0 division error
+ await expect(this.mock.$ceilDiv(a, b)).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+
+ it('does not round up a zero result', async function () {
+ const a = 0n;
+ const b = 2n;
+ const r = 0n;
+ expect(await this.mock.$ceilDiv(a, b)).to.equal(r);
+ });
+
+ it('does not round up on exact division', async function () {
+ const a = 10n;
+ const b = 5n;
+ const r = 2n;
+ expect(await this.mock.$ceilDiv(a, b)).to.equal(r);
+ });
+
+ it('rounds up on division with remainders', async function () {
+ const a = 42n;
+ const b = 13n;
+ const r = 4n;
+ expect(await this.mock.$ceilDiv(a, b)).to.equal(r);
+ });
+
+ it('does not overflow', async function () {
+ const a = ethers.MaxUint256;
+ const b = 2n;
+ const r = 1n << 255n;
+ expect(await this.mock.$ceilDiv(a, b)).to.equal(r);
+ });
+
+ it('correctly computes max uint256 divided by 1', async function () {
+ const a = ethers.MaxUint256;
+ const b = 1n;
+ const r = ethers.MaxUint256;
+ expect(await this.mock.$ceilDiv(a, b)).to.equal(r);
+ });
+ });
+
+ describe('mulDiv', function () {
+ it('divide by 0', async function () {
+ const a = 1n;
+ const b = 1n;
+ const c = 0n;
+ await expect(this.mock.$mulDiv(a, b, c, Rounding.Floor)).to.be.revertedWithPanic(PANIC_CODES.DIVISION_BY_ZERO);
+ });
+
+ it('reverts with result higher than 2 ^ 256', async function () {
+ const a = 5n;
+ const b = ethers.MaxUint256;
+ const c = 2n;
+ await expect(this.mock.$mulDiv(a, b, c, Rounding.Floor)).to.be.revertedWithPanic(
+ PANIC_CODES.ARITHMETIC_UNDER_OR_OVERFLOW,
+ );
+ });
+
+ describe('does round down', function () {
+ it('small values', async function () {
+ for (const rounding of RoundingDown) {
+ expect(await this.mock.$mulDiv(3n, 4n, 5n, rounding)).to.equal(2n);
+ expect(await this.mock.$mulDiv(3n, 5n, 5n, rounding)).to.equal(3n);
+ }
+ });
+
+ it('large values', async function () {
+ for (const rounding of RoundingDown) {
+ expect(await this.mock.$mulDiv(42n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding)).to.equal(41n);
+
+ expect(await this.mock.$mulDiv(17n, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal(17n);
+
+ expect(
+ await this.mock.$mulDiv(ethers.MaxUint256 - 1n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding),
+ ).to.equal(ethers.MaxUint256 - 2n);
+
+ expect(
+ await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding),
+ ).to.equal(ethers.MaxUint256 - 1n);
+
+ expect(await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal(
+ ethers.MaxUint256,
+ );
+ }
+ });
+ });
+
+ describe('does round up', function () {
+ it('small values', async function () {
+ for (const rounding of RoundingUp) {
+ expect(await this.mock.$mulDiv(3n, 4n, 5n, rounding)).to.equal(3n);
+ expect(await this.mock.$mulDiv(3n, 5n, 5n, rounding)).to.equal(3n);
+ }
+ });
+
+ it('large values', async function () {
+ for (const rounding of RoundingUp) {
+ expect(await this.mock.$mulDiv(42n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding)).to.equal(42n);
+
+ expect(await this.mock.$mulDiv(17n, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal(17n);
+
+ expect(
+ await this.mock.$mulDiv(ethers.MaxUint256 - 1n, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding),
+ ).to.equal(ethers.MaxUint256 - 1n);
+
+ expect(
+ await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256 - 1n, ethers.MaxUint256, rounding),
+ ).to.equal(ethers.MaxUint256 - 1n);
+
+ expect(await this.mock.$mulDiv(ethers.MaxUint256, ethers.MaxUint256, ethers.MaxUint256, rounding)).to.equal(
+ ethers.MaxUint256,
+ );
+ }
+ });
+ });
+ });
+
+ describe('invMod', function () {
+ for (const factors of [
+ [0n],
+ [1n],
+ [2n],
+ [17n],
+ [65537n],
+ [0xffffffff00000001000000000000000000000000ffffffffffffffffffffffffn],
+ [3n, 5n],
+ [3n, 7n],
+ [47n, 53n],
+ ]) {
+ const p = factors.reduce((acc, f) => acc * f, 1n);
+
+ describe(`using p=${p} which is ${p > 1 && factors.length > 1 ? 'not ' : ''}a prime`, function () {
+ it('trying to inverse 0 returns 0', async function () {
+ expect(await this.mock.$invMod(0, p)).to.equal(0n);
+ expect(await this.mock.$invMod(p, p)).to.equal(0n); // p is 0 mod p
+ });
+
+ if (p != 0) {
+ for (const value of Array.from({ length: 16 }, generators.uint256)) {
+ const isInversible = factors.every(f => value % f);
+ it(`trying to inverse ${value}`, async function () {
+ const result = await this.mock.$invMod(value, p);
+ if (isInversible) {
+ expect((value * result) % p).to.equal(1n);
+ } else {
+ expect(result).to.equal(0n);
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+
+ describe('modExp', function () {
+ for (const [name, type] of Object.entries({ uint256, bytes })) {
+ describe(`with ${name} inputs`, function () {
+ it('is correctly calculating modulus', async function () {
+ const b = 3n;
+ const e = 200n;
+ const m = 50n;
+
+ expect(await this.mock.$modExp(type(b), type(e), type(m))).to.equal(type(b ** e % m).value);
+ });
+
+ it('is correctly reverting when modulus is zero', async function () {
+ const b = 3n;
+ const e = 200n;
+ const m = 0n;
+
+ await expect(this.mock.$modExp(type(b), type(e), type(m))).to.be.revertedWithPanic(
+ PANIC_CODES.DIVISION_BY_ZERO,
+ );
+ });
+ });
+ }
+
+ describe('with large bytes inputs', function () {
+ for (const [[b, log2b], [e, log2e], [m, log2m]] of product(
+ range(320, 512, 64).map(e => [2n ** BigInt(e) + 1n, e]),
+ range(320, 512, 64).map(e => [2n ** BigInt(e) + 1n, e]),
+ range(320, 512, 64).map(e => [2n ** BigInt(e) + 1n, e]),
+ )) {
+ it(`calculates b ** e % m (b=2**${log2b}+1) (e=2**${log2e}+1) (m=2**${log2m}+1)`, async function () {
+ const mLength = ethers.dataLength(ethers.toBeHex(m));
+
+ expect(await this.mock.$modExp(bytes(b), bytes(e), bytes(m))).to.equal(bytes(modExp(b, e, m), mLength).value);
+ });
+ }
+ });
+ });
+
+ describe('tryModExp', function () {
+ for (const [name, type] of Object.entries({ uint256, bytes })) {
+ describe(`with ${name} inputs`, function () {
+ it('is correctly calculating modulus', async function () {
+ const b = 3n;
+ const e = 200n;
+ const m = 50n;
+
+ expect(await this.mock.$tryModExp(type(b), type(e), type(m))).to.deep.equal([true, type(b ** e % m).value]);
+ });
+
+ it('is correctly reverting when modulus is zero', async function () {
+ const b = 3n;
+ const e = 200n;
+ const m = 0n;
+
+ expect(await this.mock.$tryModExp(type(b), type(e), type(m))).to.deep.equal([false, type.zero]);
+ });
+ });
+ }
+
+ describe('with large bytes inputs', function () {
+ for (const [[b, log2b], [e, log2e], [m, log2m]] of product(
+ range(320, 513, 64).map(e => [2n ** BigInt(e) + 1n, e]),
+ range(320, 513, 64).map(e => [2n ** BigInt(e) + 1n, e]),
+ range(320, 513, 64).map(e => [2n ** BigInt(e) + 1n, e]),
+ )) {
+ it(`calculates b ** e % m (b=2**${log2b}+1) (e=2**${log2e}+1) (m=2**${log2m}+1)`, async function () {
+ const mLength = ethers.dataLength(ethers.toBeHex(m));
+
+ expect(await this.mock.$tryModExp(bytes(b), bytes(e), bytes(m))).to.deep.equal([
+ true,
+ bytes(modExp(b, e, m), mLength).value,
+ ]);
+ });
+ }
+ });
+ });
+
+ describe('sqrt', function () {
+ it('rounds down', async function () {
+ for (const rounding of RoundingDown) {
+ expect(await this.mock.$sqrt(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$sqrt(1n, rounding)).to.equal(1n);
+ expect(await this.mock.$sqrt(2n, rounding)).to.equal(1n);
+ expect(await this.mock.$sqrt(3n, rounding)).to.equal(1n);
+ expect(await this.mock.$sqrt(4n, rounding)).to.equal(2n);
+ expect(await this.mock.$sqrt(144n, rounding)).to.equal(12n);
+ expect(await this.mock.$sqrt(999999n, rounding)).to.equal(999n);
+ expect(await this.mock.$sqrt(1000000n, rounding)).to.equal(1000n);
+ expect(await this.mock.$sqrt(1000001n, rounding)).to.equal(1000n);
+ expect(await this.mock.$sqrt(1002000n, rounding)).to.equal(1000n);
+ expect(await this.mock.$sqrt(1002001n, rounding)).to.equal(1001n);
+ expect(await this.mock.$sqrt(ethers.MaxUint256, rounding)).to.equal(340282366920938463463374607431768211455n);
+ }
+ });
+
+ it('rounds up', async function () {
+ for (const rounding of RoundingUp) {
+ expect(await this.mock.$sqrt(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$sqrt(1n, rounding)).to.equal(1n);
+ expect(await this.mock.$sqrt(2n, rounding)).to.equal(2n);
+ expect(await this.mock.$sqrt(3n, rounding)).to.equal(2n);
+ expect(await this.mock.$sqrt(4n, rounding)).to.equal(2n);
+ expect(await this.mock.$sqrt(144n, rounding)).to.equal(12n);
+ expect(await this.mock.$sqrt(999999n, rounding)).to.equal(1000n);
+ expect(await this.mock.$sqrt(1000000n, rounding)).to.equal(1000n);
+ expect(await this.mock.$sqrt(1000001n, rounding)).to.equal(1001n);
+ expect(await this.mock.$sqrt(1002000n, rounding)).to.equal(1001n);
+ expect(await this.mock.$sqrt(1002001n, rounding)).to.equal(1001n);
+ expect(await this.mock.$sqrt(ethers.MaxUint256, rounding)).to.equal(340282366920938463463374607431768211456n);
+ }
+ });
+ });
+
+ describe('log', function () {
+ describe('log2', function () {
+ it('rounds down', async function () {
+ for (const rounding of RoundingDown) {
+ expect(await this.mock.$log2(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$log2(1n, rounding)).to.equal(0n);
+ expect(await this.mock.$log2(2n, rounding)).to.equal(1n);
+ expect(await this.mock.$log2(3n, rounding)).to.equal(1n);
+ expect(await this.mock.$log2(4n, rounding)).to.equal(2n);
+ expect(await this.mock.$log2(5n, rounding)).to.equal(2n);
+ expect(await this.mock.$log2(6n, rounding)).to.equal(2n);
+ expect(await this.mock.$log2(7n, rounding)).to.equal(2n);
+ expect(await this.mock.$log2(8n, rounding)).to.equal(3n);
+ expect(await this.mock.$log2(9n, rounding)).to.equal(3n);
+ expect(await this.mock.$log2(ethers.MaxUint256, rounding)).to.equal(255n);
+ }
+ });
+
+ it('rounds up', async function () {
+ for (const rounding of RoundingUp) {
+ expect(await this.mock.$log2(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$log2(1n, rounding)).to.equal(0n);
+ expect(await this.mock.$log2(2n, rounding)).to.equal(1n);
+ expect(await this.mock.$log2(3n, rounding)).to.equal(2n);
+ expect(await this.mock.$log2(4n, rounding)).to.equal(2n);
+ expect(await this.mock.$log2(5n, rounding)).to.equal(3n);
+ expect(await this.mock.$log2(6n, rounding)).to.equal(3n);
+ expect(await this.mock.$log2(7n, rounding)).to.equal(3n);
+ expect(await this.mock.$log2(8n, rounding)).to.equal(3n);
+ expect(await this.mock.$log2(9n, rounding)).to.equal(4n);
+ expect(await this.mock.$log2(ethers.MaxUint256, rounding)).to.equal(256n);
+ }
+ });
+ });
+
+ describe('log10', function () {
+ it('rounds down', async function () {
+ for (const rounding of RoundingDown) {
+ expect(await this.mock.$log10(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$log10(1n, rounding)).to.equal(0n);
+ expect(await this.mock.$log10(2n, rounding)).to.equal(0n);
+ expect(await this.mock.$log10(9n, rounding)).to.equal(0n);
+ expect(await this.mock.$log10(10n, rounding)).to.equal(1n);
+ expect(await this.mock.$log10(11n, rounding)).to.equal(1n);
+ expect(await this.mock.$log10(99n, rounding)).to.equal(1n);
+ expect(await this.mock.$log10(100n, rounding)).to.equal(2n);
+ expect(await this.mock.$log10(101n, rounding)).to.equal(2n);
+ expect(await this.mock.$log10(999n, rounding)).to.equal(2n);
+ expect(await this.mock.$log10(1000n, rounding)).to.equal(3n);
+ expect(await this.mock.$log10(1001n, rounding)).to.equal(3n);
+ expect(await this.mock.$log10(ethers.MaxUint256, rounding)).to.equal(77n);
+ }
+ });
+
+ it('rounds up', async function () {
+ for (const rounding of RoundingUp) {
+ expect(await this.mock.$log10(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$log10(1n, rounding)).to.equal(0n);
+ expect(await this.mock.$log10(2n, rounding)).to.equal(1n);
+ expect(await this.mock.$log10(9n, rounding)).to.equal(1n);
+ expect(await this.mock.$log10(10n, rounding)).to.equal(1n);
+ expect(await this.mock.$log10(11n, rounding)).to.equal(2n);
+ expect(await this.mock.$log10(99n, rounding)).to.equal(2n);
+ expect(await this.mock.$log10(100n, rounding)).to.equal(2n);
+ expect(await this.mock.$log10(101n, rounding)).to.equal(3n);
+ expect(await this.mock.$log10(999n, rounding)).to.equal(3n);
+ expect(await this.mock.$log10(1000n, rounding)).to.equal(3n);
+ expect(await this.mock.$log10(1001n, rounding)).to.equal(4n);
+ expect(await this.mock.$log10(ethers.MaxUint256, rounding)).to.equal(78n);
+ }
+ });
+ });
+
+ describe('log256', function () {
+ it('rounds down', async function () {
+ for (const rounding of RoundingDown) {
+ expect(await this.mock.$log256(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$log256(1n, rounding)).to.equal(0n);
+ expect(await this.mock.$log256(2n, rounding)).to.equal(0n);
+ expect(await this.mock.$log256(255n, rounding)).to.equal(0n);
+ expect(await this.mock.$log256(256n, rounding)).to.equal(1n);
+ expect(await this.mock.$log256(257n, rounding)).to.equal(1n);
+ expect(await this.mock.$log256(65535n, rounding)).to.equal(1n);
+ expect(await this.mock.$log256(65536n, rounding)).to.equal(2n);
+ expect(await this.mock.$log256(65537n, rounding)).to.equal(2n);
+ expect(await this.mock.$log256(ethers.MaxUint256, rounding)).to.equal(31n);
+ }
+ });
+
+ it('rounds up', async function () {
+ for (const rounding of RoundingUp) {
+ expect(await this.mock.$log256(0n, rounding)).to.equal(0n);
+ expect(await this.mock.$log256(1n, rounding)).to.equal(0n);
+ expect(await this.mock.$log256(2n, rounding)).to.equal(1n);
+ expect(await this.mock.$log256(255n, rounding)).to.equal(1n);
+ expect(await this.mock.$log256(256n, rounding)).to.equal(1n);
+ expect(await this.mock.$log256(257n, rounding)).to.equal(2n);
+ expect(await this.mock.$log256(65535n, rounding)).to.equal(2n);
+ expect(await this.mock.$log256(65536n, rounding)).to.equal(2n);
+ expect(await this.mock.$log256(65537n, rounding)).to.equal(3n);
+ expect(await this.mock.$log256(ethers.MaxUint256, rounding)).to.equal(32n);
+ }
+ });
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SafeCast.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SafeCast.test.js
new file mode 100644
index 000000000..ab62406ce
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SafeCast.test.js
@@ -0,0 +1,159 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { range } = require('../../helpers/iterate');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$SafeCast');
+ return { mock };
+}
+
+describe('SafeCast', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const bits of range(8, 256, 8).map(ethers.toBigInt)) {
+ const maxValue = 2n ** bits - 1n;
+
+ describe(`toUint${bits}`, () => {
+ it('downcasts 0', async function () {
+ expect(await this.mock[`$toUint${bits}`](0n)).is.equal(0n);
+ });
+
+ it('downcasts 1', async function () {
+ expect(await this.mock[`$toUint${bits}`](1n)).is.equal(1n);
+ });
+
+ it(`downcasts 2^${bits} - 1 (${maxValue})`, async function () {
+ expect(await this.mock[`$toUint${bits}`](maxValue)).is.equal(maxValue);
+ });
+
+ it(`reverts when downcasting 2^${bits} (${maxValue + 1n})`, async function () {
+ await expect(this.mock[`$toUint${bits}`](maxValue + 1n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedUintDowncast')
+ .withArgs(bits, maxValue + 1n);
+ });
+
+ it(`reverts when downcasting 2^${bits} + 1 (${maxValue + 2n})`, async function () {
+ await expect(this.mock[`$toUint${bits}`](maxValue + 2n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedUintDowncast')
+ .withArgs(bits, maxValue + 2n);
+ });
+ });
+ }
+
+ describe('toUint256', () => {
+ it('casts 0', async function () {
+ expect(await this.mock.$toUint256(0n)).is.equal(0n);
+ });
+
+ it('casts 1', async function () {
+ expect(await this.mock.$toUint256(1n)).is.equal(1n);
+ });
+
+ it(`casts INT256_MAX (${ethers.MaxInt256})`, async function () {
+ expect(await this.mock.$toUint256(ethers.MaxInt256)).is.equal(ethers.MaxInt256);
+ });
+
+ it('reverts when casting -1', async function () {
+ await expect(this.mock.$toUint256(-1n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedIntToUint')
+ .withArgs(-1n);
+ });
+
+ it(`reverts when casting INT256_MIN (${ethers.MinInt256})`, async function () {
+ await expect(this.mock.$toUint256(ethers.MinInt256))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedIntToUint')
+ .withArgs(ethers.MinInt256);
+ });
+ });
+
+ for (const bits of range(8, 256, 8).map(ethers.toBigInt)) {
+ const minValue = -(2n ** (bits - 1n));
+ const maxValue = 2n ** (bits - 1n) - 1n;
+
+ describe(`toInt${bits}`, () => {
+ it('downcasts 0', async function () {
+ expect(await this.mock[`$toInt${bits}`](0n)).is.equal(0n);
+ });
+
+ it('downcasts 1', async function () {
+ expect(await this.mock[`$toInt${bits}`](1n)).is.equal(1n);
+ });
+
+ it('downcasts -1', async function () {
+ expect(await this.mock[`$toInt${bits}`](-1n)).is.equal(-1n);
+ });
+
+ it(`downcasts -2^${bits - 1n} (${minValue})`, async function () {
+ expect(await this.mock[`$toInt${bits}`](minValue)).is.equal(minValue);
+ });
+
+ it(`downcasts 2^${bits - 1n} - 1 (${maxValue})`, async function () {
+ expect(await this.mock[`$toInt${bits}`](maxValue)).is.equal(maxValue);
+ });
+
+ it(`reverts when downcasting -2^${bits - 1n} - 1 (${minValue - 1n})`, async function () {
+ await expect(this.mock[`$toInt${bits}`](minValue - 1n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedIntDowncast')
+ .withArgs(bits, minValue - 1n);
+ });
+
+ it(`reverts when downcasting -2^${bits - 1n} - 2 (${minValue - 2n})`, async function () {
+ await expect(this.mock[`$toInt${bits}`](minValue - 2n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedIntDowncast')
+ .withArgs(bits, minValue - 2n);
+ });
+
+ it(`reverts when downcasting 2^${bits - 1n} (${maxValue + 1n})`, async function () {
+ await expect(this.mock[`$toInt${bits}`](maxValue + 1n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedIntDowncast')
+ .withArgs(bits, maxValue + 1n);
+ });
+
+ it(`reverts when downcasting 2^${bits - 1n} + 1 (${maxValue + 2n})`, async function () {
+ await expect(this.mock[`$toInt${bits}`](maxValue + 2n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedIntDowncast')
+ .withArgs(bits, maxValue + 2n);
+ });
+ });
+ }
+
+ describe('toInt256', () => {
+ it('casts 0', async function () {
+ expect(await this.mock.$toInt256(0)).is.equal(0n);
+ });
+
+ it('casts 1', async function () {
+ expect(await this.mock.$toInt256(1)).is.equal(1n);
+ });
+
+ it(`casts INT256_MAX (${ethers.MaxInt256})`, async function () {
+ expect(await this.mock.$toInt256(ethers.MaxInt256)).is.equal(ethers.MaxInt256);
+ });
+
+ it(`reverts when casting INT256_MAX + 1 (${ethers.MaxInt256 + 1n})`, async function () {
+ await expect(this.mock.$toInt256(ethers.MaxInt256 + 1n))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedUintToInt')
+ .withArgs(ethers.MaxInt256 + 1n);
+ });
+
+ it(`reverts when casting UINT256_MAX (${ethers.MaxUint256})`, async function () {
+ await expect(this.mock.$toInt256(ethers.MaxUint256))
+ .to.be.revertedWithCustomError(this.mock, 'SafeCastOverflowedUintToInt')
+ .withArgs(ethers.MaxUint256);
+ });
+ });
+
+ describe('toUint (bool)', function () {
+ it('toUint(false) should be 0', async function () {
+ expect(await this.mock.$toUint(false)).to.equal(0n);
+ });
+
+ it('toUint(true) should be 1', async function () {
+ expect(await this.mock.$toUint(true)).to.equal(1n);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SignedMath.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SignedMath.t.sol
new file mode 100644
index 000000000..bbad109b7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SignedMath.t.sol
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+
+import {Math} from "../../../contracts/utils/math/Math.sol";
+import {SignedMath} from "../../../contracts/utils/math/SignedMath.sol";
+
+contract SignedMathTest is Test {
+ function testSymbolicTernary(bool f, int256 a, int256 b) public {
+ assertEq(SignedMath.ternary(f, a, b), f ? a : b);
+ }
+
+ // MIN & MAX
+ function testSymbolicMinMax(int256 a, int256 b) public {
+ assertEq(SignedMath.min(a, b), a < b ? a : b);
+ assertEq(SignedMath.max(a, b), a > b ? a : b);
+ }
+
+ // MIN
+ function testSymbolicMin(int256 a, int256 b) public {
+ int256 result = SignedMath.min(a, b);
+
+ assertLe(result, a);
+ assertLe(result, b);
+ assertTrue(result == a || result == b);
+ }
+
+ // MAX
+ function testSymbolicMax(int256 a, int256 b) public {
+ int256 result = SignedMath.max(a, b);
+
+ assertGe(result, a);
+ assertGe(result, b);
+ assertTrue(result == a || result == b);
+ }
+
+ // AVERAGE
+ // 1. simple test, not full int256 range
+ function testAverage1(int256 a, int256 b) public {
+ a = bound(a, type(int256).min / 2, type(int256).max / 2);
+ b = bound(b, type(int256).min / 2, type(int256).max / 2);
+
+ int256 result = SignedMath.average(a, b);
+
+ assertEq(result, (a + b) / 2);
+ }
+
+ // 2. more complex test, full int256 range
+ function testAverage2(int256 a, int256 b) public {
+ (int256 result, int256 min, int256 max) = (
+ SignedMath.average(a, b),
+ SignedMath.min(a, b),
+ SignedMath.max(a, b)
+ );
+
+ // average must be between `a` and `b`
+ assertGe(result, min);
+ assertLe(result, max);
+
+ unchecked {
+ // must be unchecked in order to support `a = type(int256).min, b = type(int256).max`
+ uint256 deltaLower = uint256(result - min);
+ uint256 deltaUpper = uint256(max - result);
+ uint256 remainder = uint256((a & 1) ^ (b & 1));
+ assertEq(remainder, Math.max(deltaLower, deltaUpper) - Math.min(deltaLower, deltaUpper));
+ }
+ }
+
+ // ABS
+ function testSymbolicAbs(int256 a) public {
+ uint256 result = SignedMath.abs(a);
+
+ unchecked {
+ // must be unchecked in order to support `n = type(int256).min`
+ assertEq(result, a < 0 ? uint256(-a) : uint256(a));
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SignedMath.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SignedMath.test.js
new file mode 100644
index 000000000..877f3b480
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/math/SignedMath.test.js
@@ -0,0 +1,53 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { min, max } = require('../../helpers/math');
+
+async function testCommutative(fn, lhs, rhs, expected, ...extra) {
+ expect(await fn(lhs, rhs, ...extra)).to.deep.equal(expected);
+ expect(await fn(rhs, lhs, ...extra)).to.deep.equal(expected);
+}
+
+async function fixture() {
+ const mock = await ethers.deployContract('$SignedMath');
+ return { mock };
+}
+
+describe('SignedMath', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('max', function () {
+ it('is correctly detected in both position', async function () {
+ await testCommutative(this.mock.$max, -1234n, 5678n, max(-1234n, 5678n));
+ });
+ });
+
+ describe('min', function () {
+ it('is correctly detected in both position', async function () {
+ await testCommutative(this.mock.$min, -1234n, 5678n, min(-1234n, 5678n));
+ });
+ });
+
+ describe('average', function () {
+ it('is correctly calculated with various input', async function () {
+ for (const x of [ethers.MinInt256, -57417n, -42304n, -4n, -3n, 0n, 3n, 4n, 42304n, 57417n, ethers.MaxInt256]) {
+ for (const y of [ethers.MinInt256, -57417n, -42304n, -5n, -2n, 0n, 2n, 5n, 42304n, 57417n, ethers.MaxInt256]) {
+ expect(await this.mock.$average(x, y)).to.equal((x + y) / 2n);
+ }
+ }
+ });
+ });
+
+ describe('abs', function () {
+ const abs = x => (x < 0n ? -x : x);
+
+ for (const n of [ethers.MinInt256, ethers.MinInt256 + 1n, -1n, 0n, 1n, ethers.MaxInt256 - 1n, ethers.MaxInt256]) {
+ it(`correctly computes the absolute value of ${n}`, async function () {
+ expect(await this.mock.$abs(n)).to.equal(abs(n));
+ });
+ }
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/BitMap.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/BitMap.test.js
new file mode 100644
index 000000000..5662ab13f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/BitMap.test.js
@@ -0,0 +1,149 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+async function fixture() {
+ const bitmap = await ethers.deployContract('$BitMaps');
+ return { bitmap };
+}
+
+describe('BitMap', function () {
+ const keyA = 7891n;
+ const keyB = 451n;
+ const keyC = 9592328n;
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('starts empty', async function () {
+ expect(await this.bitmap.$get(0, keyA)).to.be.false;
+ expect(await this.bitmap.$get(0, keyB)).to.be.false;
+ expect(await this.bitmap.$get(0, keyC)).to.be.false;
+ });
+
+ describe('setTo', function () {
+ it('set a key to true', async function () {
+ await this.bitmap.$setTo(0, keyA, true);
+ expect(await this.bitmap.$get(0, keyA)).to.be.true;
+ expect(await this.bitmap.$get(0, keyB)).to.be.false;
+ expect(await this.bitmap.$get(0, keyC)).to.be.false;
+ });
+
+ it('set a key to false', async function () {
+ await this.bitmap.$setTo(0, keyA, true);
+ await this.bitmap.$setTo(0, keyA, false);
+ expect(await this.bitmap.$get(0, keyA)).to.be.false;
+ expect(await this.bitmap.$get(0, keyB)).to.be.false;
+ expect(await this.bitmap.$get(0, keyC)).to.be.false;
+ });
+
+ it('set several consecutive keys', async function () {
+ await this.bitmap.$setTo(0, keyA + 0n, true);
+ await this.bitmap.$setTo(0, keyA + 1n, true);
+ await this.bitmap.$setTo(0, keyA + 2n, true);
+ await this.bitmap.$setTo(0, keyA + 3n, true);
+ await this.bitmap.$setTo(0, keyA + 4n, true);
+ await this.bitmap.$setTo(0, keyA + 2n, false);
+ await this.bitmap.$setTo(0, keyA + 4n, false);
+ expect(await this.bitmap.$get(0, keyA + 0n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 1n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 2n)).to.be.false;
+ expect(await this.bitmap.$get(0, keyA + 3n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 4n)).to.be.false;
+ });
+ });
+
+ describe('set', function () {
+ it('adds a key', async function () {
+ await this.bitmap.$set(0, keyA);
+ expect(await this.bitmap.$get(0, keyA)).to.be.true;
+ expect(await this.bitmap.$get(0, keyB)).to.be.false;
+ expect(await this.bitmap.$get(0, keyC)).to.be.false;
+ });
+
+ it('adds several keys', async function () {
+ await this.bitmap.$set(0, keyA);
+ await this.bitmap.$set(0, keyB);
+ expect(await this.bitmap.$get(0, keyA)).to.be.true;
+ expect(await this.bitmap.$get(0, keyB)).to.be.true;
+ expect(await this.bitmap.$get(0, keyC)).to.be.false;
+ });
+
+ it('adds several consecutive keys', async function () {
+ await this.bitmap.$set(0, keyA + 0n);
+ await this.bitmap.$set(0, keyA + 1n);
+ await this.bitmap.$set(0, keyA + 3n);
+ expect(await this.bitmap.$get(0, keyA + 0n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 1n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 2n)).to.be.false;
+ expect(await this.bitmap.$get(0, keyA + 3n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 4n)).to.be.false;
+ });
+ });
+
+ describe('unset', function () {
+ it('removes added keys', async function () {
+ await this.bitmap.$set(0, keyA);
+ await this.bitmap.$set(0, keyB);
+ await this.bitmap.$unset(0, keyA);
+ expect(await this.bitmap.$get(0, keyA)).to.be.false;
+ expect(await this.bitmap.$get(0, keyB)).to.be.true;
+ expect(await this.bitmap.$get(0, keyC)).to.be.false;
+ });
+
+ it('removes consecutive added keys', async function () {
+ await this.bitmap.$set(0, keyA + 0n);
+ await this.bitmap.$set(0, keyA + 1n);
+ await this.bitmap.$set(0, keyA + 3n);
+ await this.bitmap.$unset(0, keyA + 1n);
+ expect(await this.bitmap.$get(0, keyA + 0n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 1n)).to.be.false;
+ expect(await this.bitmap.$get(0, keyA + 2n)).to.be.false;
+ expect(await this.bitmap.$get(0, keyA + 3n)).to.be.true;
+ expect(await this.bitmap.$get(0, keyA + 4n)).to.be.false;
+ });
+
+ it('adds and removes multiple keys', async function () {
+ // []
+
+ await this.bitmap.$set(0, keyA);
+ await this.bitmap.$set(0, keyC);
+
+ // [A, C]
+
+ await this.bitmap.$unset(0, keyA);
+ await this.bitmap.$unset(0, keyB);
+
+ // [C]
+
+ await this.bitmap.$set(0, keyB);
+
+ // [C, B]
+
+ await this.bitmap.$set(0, keyA);
+ await this.bitmap.$unset(0, keyC);
+
+ // [A, B]
+
+ await this.bitmap.$set(0, keyA);
+ await this.bitmap.$set(0, keyB);
+
+ // [A, B]
+
+ await this.bitmap.$set(0, keyC);
+ await this.bitmap.$unset(0, keyA);
+
+ // [B, C]
+
+ await this.bitmap.$set(0, keyA);
+ await this.bitmap.$unset(0, keyB);
+
+ // [A, C]
+
+ expect(await this.bitmap.$get(0, keyA)).to.be.true;
+ expect(await this.bitmap.$get(0, keyB)).to.be.false;
+ expect(await this.bitmap.$get(0, keyC)).to.be.true;
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.t.sol
new file mode 100644
index 000000000..1f4b344c5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.t.sol
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: MIT
+// This file was procedurally generated from scripts/generate/templates/Checkpoints.t.js.
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
+import {Checkpoints} from "@openzeppelin/contracts/utils/structs/Checkpoints.sol";
+
+contract CheckpointsTrace224Test is Test {
+ using Checkpoints for Checkpoints.Trace224;
+
+ // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function with make sure that
+ // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range.
+ uint8 internal constant _KEY_MAX_GAP = 64;
+
+ Checkpoints.Trace224 internal _ckpts;
+
+ // helpers
+ function _boundUint32(uint32 x, uint32 min, uint32 max) internal pure returns (uint32) {
+ return SafeCast.toUint32(bound(uint256(x), uint256(min), uint256(max)));
+ }
+
+ function _prepareKeys(uint32[] memory keys, uint32 maxSpread) internal pure {
+ uint32 lastKey = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint32 key = _boundUint32(keys[i], lastKey, lastKey + maxSpread);
+ keys[i] = key;
+ lastKey = key;
+ }
+ }
+
+ function _assertLatestCheckpoint(bool exist, uint32 key, uint224 value) internal {
+ (bool _exist, uint32 _key, uint224 _value) = _ckpts.latestCheckpoint();
+ assertEq(_exist, exist);
+ assertEq(_key, key);
+ assertEq(_value, value);
+ }
+
+ // tests
+ function testPush(uint32[] memory keys, uint224[] memory values, uint32 pastKey) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ // initial state
+ assertEq(_ckpts.length(), 0);
+ assertEq(_ckpts.latest(), 0);
+ _assertLatestCheckpoint(false, 0, 0);
+
+ uint256 duplicates = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint32 key = keys[i];
+ uint224 value = values[i % values.length];
+ if (i > 0 && key == keys[i - 1]) ++duplicates;
+
+ // push
+ _ckpts.push(key, value);
+
+ // check length & latest
+ assertEq(_ckpts.length(), i + 1 - duplicates);
+ assertEq(_ckpts.latest(), value);
+ _assertLatestCheckpoint(true, key, value);
+ }
+
+ if (keys.length > 0) {
+ uint32 lastKey = keys[keys.length - 1];
+ if (lastKey > 0) {
+ pastKey = _boundUint32(pastKey, 0, lastKey - 1);
+
+ vm.expectRevert();
+ this.push(pastKey, values[keys.length % values.length]);
+ }
+ }
+ }
+
+ // used to test reverts
+ function push(uint32 key, uint224 value) external {
+ _ckpts.push(key, value);
+ }
+
+ function testLookup(uint32[] memory keys, uint224[] memory values, uint32 lookup) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ uint32 lastKey = keys.length == 0 ? 0 : keys[keys.length - 1];
+ lookup = _boundUint32(lookup, 0, lastKey + _KEY_MAX_GAP);
+
+ uint224 upper = 0;
+ uint224 lower = 0;
+ uint32 lowerKey = type(uint32).max;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint32 key = keys[i];
+ uint224 value = values[i % values.length];
+
+ // push
+ _ckpts.push(key, value);
+
+ // track expected result of lookups
+ if (key <= lookup) {
+ upper = value;
+ }
+ // find the first key that is not smaller than the lookup key
+ if (key >= lookup && (i == 0 || keys[i - 1] < lookup)) {
+ lowerKey = key;
+ }
+ if (key == lowerKey) {
+ lower = value;
+ }
+ }
+
+ // check lookup
+ assertEq(_ckpts.lowerLookup(lookup), lower);
+ assertEq(_ckpts.upperLookup(lookup), upper);
+ assertEq(_ckpts.upperLookupRecent(lookup), upper);
+ }
+}
+
+contract CheckpointsTrace208Test is Test {
+ using Checkpoints for Checkpoints.Trace208;
+
+ // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function with make sure that
+ // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range.
+ uint8 internal constant _KEY_MAX_GAP = 64;
+
+ Checkpoints.Trace208 internal _ckpts;
+
+ // helpers
+ function _boundUint48(uint48 x, uint48 min, uint48 max) internal pure returns (uint48) {
+ return SafeCast.toUint48(bound(uint256(x), uint256(min), uint256(max)));
+ }
+
+ function _prepareKeys(uint48[] memory keys, uint48 maxSpread) internal pure {
+ uint48 lastKey = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint48 key = _boundUint48(keys[i], lastKey, lastKey + maxSpread);
+ keys[i] = key;
+ lastKey = key;
+ }
+ }
+
+ function _assertLatestCheckpoint(bool exist, uint48 key, uint208 value) internal {
+ (bool _exist, uint48 _key, uint208 _value) = _ckpts.latestCheckpoint();
+ assertEq(_exist, exist);
+ assertEq(_key, key);
+ assertEq(_value, value);
+ }
+
+ // tests
+ function testPush(uint48[] memory keys, uint208[] memory values, uint48 pastKey) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ // initial state
+ assertEq(_ckpts.length(), 0);
+ assertEq(_ckpts.latest(), 0);
+ _assertLatestCheckpoint(false, 0, 0);
+
+ uint256 duplicates = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint48 key = keys[i];
+ uint208 value = values[i % values.length];
+ if (i > 0 && key == keys[i - 1]) ++duplicates;
+
+ // push
+ _ckpts.push(key, value);
+
+ // check length & latest
+ assertEq(_ckpts.length(), i + 1 - duplicates);
+ assertEq(_ckpts.latest(), value);
+ _assertLatestCheckpoint(true, key, value);
+ }
+
+ if (keys.length > 0) {
+ uint48 lastKey = keys[keys.length - 1];
+ if (lastKey > 0) {
+ pastKey = _boundUint48(pastKey, 0, lastKey - 1);
+
+ vm.expectRevert();
+ this.push(pastKey, values[keys.length % values.length]);
+ }
+ }
+ }
+
+ // used to test reverts
+ function push(uint48 key, uint208 value) external {
+ _ckpts.push(key, value);
+ }
+
+ function testLookup(uint48[] memory keys, uint208[] memory values, uint48 lookup) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ uint48 lastKey = keys.length == 0 ? 0 : keys[keys.length - 1];
+ lookup = _boundUint48(lookup, 0, lastKey + _KEY_MAX_GAP);
+
+ uint208 upper = 0;
+ uint208 lower = 0;
+ uint48 lowerKey = type(uint48).max;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint48 key = keys[i];
+ uint208 value = values[i % values.length];
+
+ // push
+ _ckpts.push(key, value);
+
+ // track expected result of lookups
+ if (key <= lookup) {
+ upper = value;
+ }
+ // find the first key that is not smaller than the lookup key
+ if (key >= lookup && (i == 0 || keys[i - 1] < lookup)) {
+ lowerKey = key;
+ }
+ if (key == lowerKey) {
+ lower = value;
+ }
+ }
+
+ // check lookup
+ assertEq(_ckpts.lowerLookup(lookup), lower);
+ assertEq(_ckpts.upperLookup(lookup), upper);
+ assertEq(_ckpts.upperLookupRecent(lookup), upper);
+ }
+}
+
+contract CheckpointsTrace160Test is Test {
+ using Checkpoints for Checkpoints.Trace160;
+
+ // Maximum gap between keys used during the fuzzing tests: the `_prepareKeys` function with make sure that
+ // key#n+1 is in the [key#n, key#n + _KEY_MAX_GAP] range.
+ uint8 internal constant _KEY_MAX_GAP = 64;
+
+ Checkpoints.Trace160 internal _ckpts;
+
+ // helpers
+ function _boundUint96(uint96 x, uint96 min, uint96 max) internal pure returns (uint96) {
+ return SafeCast.toUint96(bound(uint256(x), uint256(min), uint256(max)));
+ }
+
+ function _prepareKeys(uint96[] memory keys, uint96 maxSpread) internal pure {
+ uint96 lastKey = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint96 key = _boundUint96(keys[i], lastKey, lastKey + maxSpread);
+ keys[i] = key;
+ lastKey = key;
+ }
+ }
+
+ function _assertLatestCheckpoint(bool exist, uint96 key, uint160 value) internal {
+ (bool _exist, uint96 _key, uint160 _value) = _ckpts.latestCheckpoint();
+ assertEq(_exist, exist);
+ assertEq(_key, key);
+ assertEq(_value, value);
+ }
+
+ // tests
+ function testPush(uint96[] memory keys, uint160[] memory values, uint96 pastKey) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ // initial state
+ assertEq(_ckpts.length(), 0);
+ assertEq(_ckpts.latest(), 0);
+ _assertLatestCheckpoint(false, 0, 0);
+
+ uint256 duplicates = 0;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint96 key = keys[i];
+ uint160 value = values[i % values.length];
+ if (i > 0 && key == keys[i - 1]) ++duplicates;
+
+ // push
+ _ckpts.push(key, value);
+
+ // check length & latest
+ assertEq(_ckpts.length(), i + 1 - duplicates);
+ assertEq(_ckpts.latest(), value);
+ _assertLatestCheckpoint(true, key, value);
+ }
+
+ if (keys.length > 0) {
+ uint96 lastKey = keys[keys.length - 1];
+ if (lastKey > 0) {
+ pastKey = _boundUint96(pastKey, 0, lastKey - 1);
+
+ vm.expectRevert();
+ this.push(pastKey, values[keys.length % values.length]);
+ }
+ }
+ }
+
+ // used to test reverts
+ function push(uint96 key, uint160 value) external {
+ _ckpts.push(key, value);
+ }
+
+ function testLookup(uint96[] memory keys, uint160[] memory values, uint96 lookup) public {
+ vm.assume(values.length > 0 && values.length <= keys.length);
+ _prepareKeys(keys, _KEY_MAX_GAP);
+
+ uint96 lastKey = keys.length == 0 ? 0 : keys[keys.length - 1];
+ lookup = _boundUint96(lookup, 0, lastKey + _KEY_MAX_GAP);
+
+ uint160 upper = 0;
+ uint160 lower = 0;
+ uint96 lowerKey = type(uint96).max;
+ for (uint256 i = 0; i < keys.length; ++i) {
+ uint96 key = keys[i];
+ uint160 value = values[i % values.length];
+
+ // push
+ _ckpts.push(key, value);
+
+ // track expected result of lookups
+ if (key <= lookup) {
+ upper = value;
+ }
+ // find the first key that is not smaller than the lookup key
+ if (key >= lookup && (i == 0 || keys[i - 1] < lookup)) {
+ lowerKey = key;
+ }
+ if (key == lowerKey) {
+ lower = value;
+ }
+ }
+
+ // check lookup
+ assertEq(_ckpts.lowerLookup(lookup), lower);
+ assertEq(_ckpts.upperLookup(lookup), upper);
+ assertEq(_ckpts.upperLookupRecent(lookup), upper);
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.test.js
new file mode 100644
index 000000000..fd22544b9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Checkpoints.test.js
@@ -0,0 +1,146 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { VALUE_SIZES } = require('../../../scripts/generate/templates/Checkpoints.opts');
+
+describe('Checkpoints', function () {
+ for (const length of VALUE_SIZES) {
+ describe(`Trace${length}`, function () {
+ const fixture = async () => {
+ const mock = await ethers.deployContract('$Checkpoints');
+ const methods = {
+ at: (...args) => mock.getFunction(`$at_Checkpoints_Trace${length}`)(0, ...args),
+ latest: (...args) => mock.getFunction(`$latest_Checkpoints_Trace${length}`)(0, ...args),
+ latestCheckpoint: (...args) => mock.getFunction(`$latestCheckpoint_Checkpoints_Trace${length}`)(0, ...args),
+ length: (...args) => mock.getFunction(`$length_Checkpoints_Trace${length}`)(0, ...args),
+ push: (...args) => mock.getFunction(`$push(uint256,uint${256 - length},uint${length})`)(0, ...args),
+ lowerLookup: (...args) => mock.getFunction(`$lowerLookup(uint256,uint${256 - length})`)(0, ...args),
+ upperLookup: (...args) => mock.getFunction(`$upperLookup(uint256,uint${256 - length})`)(0, ...args),
+ upperLookupRecent: (...args) =>
+ mock.getFunction(`$upperLookupRecent(uint256,uint${256 - length})`)(0, ...args),
+ };
+
+ return { mock, methods };
+ };
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('without checkpoints', function () {
+ it('at zero reverts', async function () {
+ // Reverts with array out of bound access, which is unspecified
+ await expect(this.methods.at(0)).to.be.reverted;
+ });
+
+ it('returns zero as latest value', async function () {
+ expect(await this.methods.latest()).to.equal(0n);
+
+ const ckpt = await this.methods.latestCheckpoint();
+ expect(ckpt[0]).to.be.false;
+ expect(ckpt[1]).to.equal(0n);
+ expect(ckpt[2]).to.equal(0n);
+ });
+
+ it('lookup returns 0', async function () {
+ expect(await this.methods.lowerLookup(0)).to.equal(0n);
+ expect(await this.methods.upperLookup(0)).to.equal(0n);
+ expect(await this.methods.upperLookupRecent(0)).to.equal(0n);
+ });
+ });
+
+ describe('with checkpoints', function () {
+ beforeEach('pushing checkpoints', async function () {
+ this.checkpoints = [
+ { key: 2n, value: 17n },
+ { key: 3n, value: 42n },
+ { key: 5n, value: 101n },
+ { key: 7n, value: 23n },
+ { key: 11n, value: 99n },
+ ];
+ for (const { key, value } of this.checkpoints) {
+ await this.methods.push(key, value);
+ }
+ });
+
+ it('at keys', async function () {
+ for (const [index, { key, value }] of this.checkpoints.entries()) {
+ const at = await this.methods.at(index);
+ expect(at._value).to.equal(value);
+ expect(at._key).to.equal(key);
+ }
+ });
+
+ it('length', async function () {
+ expect(await this.methods.length()).to.equal(this.checkpoints.length);
+ });
+
+ it('returns latest value', async function () {
+ const latest = this.checkpoints.at(-1);
+ expect(await this.methods.latest()).to.equal(latest.value);
+ expect(await this.methods.latestCheckpoint()).to.deep.equal([true, latest.key, latest.value]);
+ });
+
+ it('cannot push values in the past', async function () {
+ await expect(this.methods.push(this.checkpoints.at(-1).key - 1n, 0n)).to.be.revertedWithCustomError(
+ this.mock,
+ 'CheckpointUnorderedInsertion',
+ );
+ });
+
+ it('can update last value', async function () {
+ const newValue = 42n;
+
+ // check length before the update
+ expect(await this.methods.length()).to.equal(this.checkpoints.length);
+
+ // update last key
+ await this.methods.push(this.checkpoints.at(-1).key, newValue);
+ expect(await this.methods.latest()).to.equal(newValue);
+
+ // check that length did not change
+ expect(await this.methods.length()).to.equal(this.checkpoints.length);
+ });
+
+ it('lower lookup', async function () {
+ for (let i = 0; i < 14; ++i) {
+ const value = this.checkpoints.find(x => i <= x.key)?.value || 0n;
+
+ expect(await this.methods.lowerLookup(i)).to.equal(value);
+ }
+ });
+
+ it('upper lookup & upperLookupRecent', async function () {
+ for (let i = 0; i < 14; ++i) {
+ const value = this.checkpoints.findLast(x => i >= x.key)?.value || 0n;
+
+ expect(await this.methods.upperLookup(i)).to.equal(value);
+ expect(await this.methods.upperLookupRecent(i)).to.equal(value);
+ }
+ });
+
+ it('upperLookupRecent with more than 5 checkpoints', async function () {
+ const moreCheckpoints = [
+ { key: 12n, value: 22n },
+ { key: 13n, value: 131n },
+ { key: 17n, value: 45n },
+ { key: 19n, value: 31452n },
+ { key: 21n, value: 0n },
+ ];
+ const allCheckpoints = [].concat(this.checkpoints, moreCheckpoints);
+
+ for (const { key, value } of moreCheckpoints) {
+ await this.methods.push(key, value);
+ }
+
+ for (let i = 0; i < 25; ++i) {
+ const value = allCheckpoints.findLast(x => i >= x.key)?.value || 0n;
+ expect(await this.methods.upperLookup(i)).to.equal(value);
+ expect(await this.methods.upperLookupRecent(i)).to.equal(value);
+ }
+ });
+ });
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/CircularBuffer.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/CircularBuffer.test.js
new file mode 100644
index 000000000..e79ba6923
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/CircularBuffer.test.js
@@ -0,0 +1,83 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+const { generators } = require('../../helpers/random');
+
+const LENGTH = 4;
+
+async function fixture() {
+ const mock = await ethers.deployContract('$CircularBuffer');
+ await mock.$setup(0, LENGTH);
+ return { mock };
+}
+
+describe('CircularBuffer', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('reverts on invalid setup', async function () {
+ await expect(this.mock.$setup(0, 0)).to.be.revertedWithCustomError(this.mock, 'InvalidBufferSize');
+ });
+
+ it('starts empty', async function () {
+ expect(await this.mock.$count(0)).to.equal(0n);
+ expect(await this.mock.$length(0)).to.equal(LENGTH);
+ expect(await this.mock.$includes(0, ethers.ZeroHash)).to.be.false;
+ await expect(this.mock.$last(0, 0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ });
+
+ it('push', async function () {
+ const values = Array.from({ length: LENGTH + 3 }, generators.bytes32);
+
+ for (const [i, value] of values.map((v, i) => [i, v])) {
+ // push value
+ await this.mock.$push(0, value);
+
+ // view of the values
+ const pushed = values.slice(0, i + 1);
+ const stored = pushed.slice(-LENGTH);
+ const dropped = pushed.slice(0, -LENGTH);
+
+ // check count
+ expect(await this.mock.$length(0)).to.equal(LENGTH);
+ expect(await this.mock.$count(0)).to.equal(stored.length);
+
+ // check last
+ for (const j in stored) {
+ expect(await this.mock.$last(0, j)).to.equal(stored.at(-j - 1));
+ }
+ await expect(this.mock.$last(0, stored.length + 1)).to.be.revertedWithPanic(
+ PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS,
+ );
+
+ // check included and non-included values
+ for (const v of stored) {
+ expect(await this.mock.$includes(0, v)).to.be.true;
+ }
+ for (const v of dropped) {
+ expect(await this.mock.$includes(0, v)).to.be.false;
+ }
+ expect(await this.mock.$includes(0, ethers.ZeroHash)).to.be.false;
+ }
+ });
+
+ it('clear', async function () {
+ const value = generators.bytes32();
+ await this.mock.$push(0, value);
+
+ expect(await this.mock.$count(0)).to.equal(1n);
+ expect(await this.mock.$length(0)).to.equal(LENGTH);
+ expect(await this.mock.$includes(0, value)).to.be.true;
+ await this.mock.$last(0, 0); // not revert
+
+ await this.mock.$clear(0);
+
+ expect(await this.mock.$count(0)).to.equal(0n);
+ expect(await this.mock.$length(0)).to.equal(LENGTH);
+ expect(await this.mock.$includes(0, value)).to.be.false;
+ await expect(this.mock.$last(0, 0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/DoubleEndedQueue.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/DoubleEndedQueue.test.js
new file mode 100644
index 000000000..3615dfbf4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/DoubleEndedQueue.test.js
@@ -0,0 +1,102 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$DoubleEndedQueue');
+
+ /** Rebuild the content of the deque as a JS array. */
+ const getContent = () =>
+ mock.$length(0).then(length => Promise.all(Array.from({ length: Number(length) }, (_, i) => mock.$at(0, i))));
+
+ return { mock, getContent };
+}
+
+describe('DoubleEndedQueue', function () {
+ const coder = ethers.AbiCoder.defaultAbiCoder();
+ const bytesA = coder.encode(['uint256'], [0xdeadbeef]);
+ const bytesB = coder.encode(['uint256'], [0x0123456789]);
+ const bytesC = coder.encode(['uint256'], [0x42424242]);
+ const bytesD = coder.encode(['uint256'], [0x171717]);
+
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('when empty', function () {
+ it('getters', async function () {
+ expect(await this.mock.$empty(0)).to.be.true;
+ expect(await this.getContent()).to.have.ordered.members([]);
+ });
+
+ it('reverts on accesses', async function () {
+ await expect(this.mock.$popBack(0)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ await expect(this.mock.$popFront(0)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ await expect(this.mock.$back(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ await expect(this.mock.$front(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ });
+ });
+
+ describe('when not empty', function () {
+ beforeEach(async function () {
+ await this.mock.$pushBack(0, bytesB);
+ await this.mock.$pushFront(0, bytesA);
+ await this.mock.$pushBack(0, bytesC);
+ this.content = [bytesA, bytesB, bytesC];
+ });
+
+ it('getters', async function () {
+ expect(await this.mock.$empty(0)).to.be.false;
+ expect(await this.mock.$length(0)).to.equal(this.content.length);
+ expect(await this.mock.$front(0)).to.equal(this.content[0]);
+ expect(await this.mock.$back(0)).to.equal(this.content[this.content.length - 1]);
+ expect(await this.getContent()).to.have.ordered.members(this.content);
+ });
+
+ it('out of bounds access', async function () {
+ await expect(this.mock.$at(0, this.content.length)).to.be.revertedWithPanic(
+ PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS,
+ );
+ });
+
+ describe('push', function () {
+ it('front', async function () {
+ await this.mock.$pushFront(0, bytesD);
+ this.content.unshift(bytesD); // add element at the beginning
+
+ expect(await this.getContent()).to.have.ordered.members(this.content);
+ });
+
+ it('back', async function () {
+ await this.mock.$pushBack(0, bytesD);
+ this.content.push(bytesD); // add element at the end
+
+ expect(await this.getContent()).to.have.ordered.members(this.content);
+ });
+ });
+
+ describe('pop', function () {
+ it('front', async function () {
+ const value = this.content.shift(); // remove first element
+ await expect(this.mock.$popFront(0)).to.emit(this.mock, 'return$popFront').withArgs(value);
+
+ expect(await this.getContent()).to.have.ordered.members(this.content);
+ });
+
+ it('back', async function () {
+ const value = this.content.pop(); // remove last element
+ await expect(this.mock.$popBack(0)).to.emit(this.mock, 'return$popBack').withArgs(value);
+
+ expect(await this.getContent()).to.have.ordered.members(this.content);
+ });
+ });
+
+ it('clear', async function () {
+ await this.mock.$clear(0);
+
+ expect(await this.mock.$empty(0)).to.be.true;
+ expect(await this.getContent()).to.have.ordered.members([]);
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.behavior.js
new file mode 100644
index 000000000..37da41795
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.behavior.js
@@ -0,0 +1,151 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+
+const zip = (array1, array2) => array1.map((item, index) => [item, array2[index]]);
+
+function shouldBehaveLikeMap() {
+ async function expectMembersMatch(methods, keys, values) {
+ expect(keys.length).to.equal(values.length);
+ expect(await methods.length()).to.equal(keys.length);
+ expect([...(await methods.keys())]).to.have.members(keys);
+
+ for (const [key, value] of zip(keys, values)) {
+ expect(await methods.contains(key)).to.be.true;
+ expect(await methods.get(key)).to.equal(value);
+ }
+
+ expect(await Promise.all(keys.map((_, index) => methods.at(index)))).to.have.deep.members(zip(keys, values));
+ }
+
+ it('starts empty', async function () {
+ expect(await this.methods.contains(this.keyA)).to.be.false;
+
+ await expectMembersMatch(this.methods, [], []);
+ });
+
+ describe('set', function () {
+ it('adds a key', async function () {
+ await expect(this.methods.set(this.keyA, this.valueA)).to.emit(this.mock, this.events.setReturn).withArgs(true);
+
+ await expectMembersMatch(this.methods, [this.keyA], [this.valueA]);
+ });
+
+ it('adds several keys', async function () {
+ await this.methods.set(this.keyA, this.valueA);
+ await this.methods.set(this.keyB, this.valueB);
+
+ await expectMembersMatch(this.methods, [this.keyA, this.keyB], [this.valueA, this.valueB]);
+ expect(await this.methods.contains(this.keyC)).to.be.false;
+ });
+
+ it('returns false when adding keys already in the set', async function () {
+ await this.methods.set(this.keyA, this.valueA);
+
+ await expect(this.methods.set(this.keyA, this.valueA)).to.emit(this.mock, this.events.setReturn).withArgs(false);
+
+ await expectMembersMatch(this.methods, [this.keyA], [this.valueA]);
+ });
+
+ it('updates values for keys already in the set', async function () {
+ await this.methods.set(this.keyA, this.valueA);
+ await this.methods.set(this.keyA, this.valueB);
+
+ await expectMembersMatch(this.methods, [this.keyA], [this.valueB]);
+ });
+ });
+
+ describe('remove', function () {
+ it('removes added keys', async function () {
+ await this.methods.set(this.keyA, this.valueA);
+
+ await expect(this.methods.remove(this.keyA)).to.emit(this.mock, this.events.removeReturn).withArgs(true);
+
+ expect(await this.methods.contains(this.keyA)).to.be.false;
+ await expectMembersMatch(this.methods, [], []);
+ });
+
+ it('returns false when removing keys not in the set', async function () {
+ await expect(await this.methods.remove(this.keyA))
+ .to.emit(this.mock, this.events.removeReturn)
+ .withArgs(false);
+
+ expect(await this.methods.contains(this.keyA)).to.be.false;
+ });
+
+ it('adds and removes multiple keys', async function () {
+ // []
+
+ await this.methods.set(this.keyA, this.valueA);
+ await this.methods.set(this.keyC, this.valueC);
+
+ // [A, C]
+
+ await this.methods.remove(this.keyA);
+ await this.methods.remove(this.keyB);
+
+ // [C]
+
+ await this.methods.set(this.keyB, this.valueB);
+
+ // [C, B]
+
+ await this.methods.set(this.keyA, this.valueA);
+ await this.methods.remove(this.keyC);
+
+ // [A, B]
+
+ await this.methods.set(this.keyA, this.valueA);
+ await this.methods.set(this.keyB, this.valueB);
+
+ // [A, B]
+
+ await this.methods.set(this.keyC, this.valueC);
+ await this.methods.remove(this.keyA);
+
+ // [B, C]
+
+ await this.methods.set(this.keyA, this.valueA);
+ await this.methods.remove(this.keyB);
+
+ // [A, C]
+
+ await expectMembersMatch(this.methods, [this.keyA, this.keyC], [this.valueA, this.valueC]);
+
+ expect(await this.methods.contains(this.keyA)).to.be.true;
+ expect(await this.methods.contains(this.keyB)).to.be.false;
+ expect(await this.methods.contains(this.keyC)).to.be.true;
+ });
+ });
+
+ describe('read', function () {
+ beforeEach(async function () {
+ await this.methods.set(this.keyA, this.valueA);
+ });
+
+ describe('get', function () {
+ it('existing value', async function () {
+ expect(await this.methods.get(this.keyA)).to.equal(this.valueA);
+ });
+
+ it('missing value', async function () {
+ await expect(this.methods.get(this.keyB))
+ .to.be.revertedWithCustomError(this.mock, 'EnumerableMapNonexistentKey')
+ .withArgs(ethers.AbiCoder.defaultAbiCoder().encode([this.keyType], [this.keyB]));
+ });
+ });
+
+ describe('tryGet', function () {
+ it('existing value', async function () {
+ expect(await this.methods.tryGet(this.keyA)).to.have.ordered.members([true, this.valueA]);
+ });
+
+ it('missing value', async function () {
+ expect(await this.methods.tryGet(this.keyB)).to.have.ordered.members([false, this.zeroValue]);
+ });
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeMap,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.test.js
new file mode 100644
index 000000000..5362e873a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableMap.test.js
@@ -0,0 +1,65 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { mapValues } = require('../../helpers/iterate');
+const { generators } = require('../../helpers/random');
+const { TYPES, formatType } = require('../../../scripts/generate/templates/EnumerableMap.opts');
+
+const { shouldBehaveLikeMap } = require('./EnumerableMap.behavior');
+
+// Add Bytes32ToBytes32Map that must be tested but is not part of the generated types.
+TYPES.unshift(formatType('bytes32', 'bytes32'));
+
+async function fixture() {
+ const mock = await ethers.deployContract('$EnumerableMap');
+ const env = Object.fromEntries(
+ TYPES.map(({ name, keyType, valueType }) => [
+ name,
+ {
+ keyType,
+ keys: Array.from({ length: 3 }, generators[keyType]),
+ values: Array.from({ length: 3 }, generators[valueType]),
+ zeroValue: generators[valueType].zero,
+ methods: mapValues(
+ {
+ set: `$set(uint256,${keyType},${valueType})`,
+ get: `$get_EnumerableMap_${name}(uint256,${keyType})`,
+ tryGet: `$tryGet_EnumerableMap_${name}(uint256,${keyType})`,
+ remove: `$remove_EnumerableMap_${name}(uint256,${keyType})`,
+ length: `$length_EnumerableMap_${name}(uint256)`,
+ at: `$at_EnumerableMap_${name}(uint256,uint256)`,
+ contains: `$contains_EnumerableMap_${name}(uint256,${keyType})`,
+ keys: `$keys_EnumerableMap_${name}(uint256)`,
+ },
+ fnSig =>
+ (...args) =>
+ mock.getFunction(fnSig)(0, ...args),
+ ),
+ events: {
+ setReturn: `return$set_EnumerableMap_${name}_${keyType}_${valueType}`,
+ removeReturn: `return$remove_EnumerableMap_${name}_${keyType}`,
+ },
+ },
+ ]),
+ );
+
+ return { mock, env };
+}
+
+describe('EnumerableMap', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const { name } of TYPES) {
+ describe(name, function () {
+ beforeEach(async function () {
+ Object.assign(this, this.env[name]);
+ [this.keyA, this.keyB, this.keyC] = this.keys;
+ [this.valueA, this.valueB, this.valueC] = this.values;
+ });
+
+ shouldBehaveLikeMap();
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.behavior.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.behavior.js
new file mode 100644
index 000000000..d3d4f26d5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.behavior.js
@@ -0,0 +1,116 @@
+const { expect } = require('chai');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+function shouldBehaveLikeSet() {
+ async function expectMembersMatch(methods, values) {
+ expect(await methods.length()).to.equal(values.length);
+ for (const value of values) expect(await methods.contains(value)).to.be.true;
+
+ expect(await Promise.all(values.map((_, index) => methods.at(index)))).to.have.deep.members(values);
+ expect([...(await methods.values())]).to.have.deep.members(values);
+ }
+
+ it('starts empty', async function () {
+ expect(await this.methods.contains(this.valueA)).to.be.false;
+
+ await expectMembersMatch(this.methods, []);
+ });
+
+ describe('add', function () {
+ it('adds a value', async function () {
+ await expect(this.methods.add(this.valueA)).to.emit(this.mock, this.events.addReturn).withArgs(true);
+
+ await expectMembersMatch(this.methods, [this.valueA]);
+ });
+
+ it('adds several values', async function () {
+ await this.methods.add(this.valueA);
+ await this.methods.add(this.valueB);
+
+ await expectMembersMatch(this.methods, [this.valueA, this.valueB]);
+ expect(await this.methods.contains(this.valueC)).to.be.false;
+ });
+
+ it('returns false when adding values already in the set', async function () {
+ await this.methods.add(this.valueA);
+
+ await expect(this.methods.add(this.valueA)).to.emit(this.mock, this.events.addReturn).withArgs(false);
+
+ await expectMembersMatch(this.methods, [this.valueA]);
+ });
+ });
+
+ describe('at', function () {
+ it('reverts when retrieving non-existent elements', async function () {
+ await expect(this.methods.at(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ });
+
+ it('retrieves existing element', async function () {
+ await this.methods.add(this.valueA);
+ expect(await this.methods.at(0)).to.equal(this.valueA);
+ });
+ });
+
+ describe('remove', function () {
+ it('removes added values', async function () {
+ await this.methods.add(this.valueA);
+
+ await expect(this.methods.remove(this.valueA)).to.emit(this.mock, this.events.removeReturn).withArgs(true);
+
+ expect(await this.methods.contains(this.valueA)).to.be.false;
+ await expectMembersMatch(this.methods, []);
+ });
+
+ it('returns false when removing values not in the set', async function () {
+ await expect(this.methods.remove(this.valueA)).to.emit(this.mock, this.events.removeReturn).withArgs(false);
+
+ expect(await this.methods.contains(this.valueA)).to.be.false;
+ });
+
+ it('adds and removes multiple values', async function () {
+ // []
+
+ await this.methods.add(this.valueA);
+ await this.methods.add(this.valueC);
+
+ // [A, C]
+
+ await this.methods.remove(this.valueA);
+ await this.methods.remove(this.valueB);
+
+ // [C]
+
+ await this.methods.add(this.valueB);
+
+ // [C, B]
+
+ await this.methods.add(this.valueA);
+ await this.methods.remove(this.valueC);
+
+ // [A, B]
+
+ await this.methods.add(this.valueA);
+ await this.methods.add(this.valueB);
+
+ // [A, B]
+
+ await this.methods.add(this.valueC);
+ await this.methods.remove(this.valueA);
+
+ // [B, C]
+
+ await this.methods.add(this.valueA);
+ await this.methods.remove(this.valueB);
+
+ // [A, C]
+
+ await expectMembersMatch(this.methods, [this.valueA, this.valueC]);
+
+ expect(await this.methods.contains(this.valueB)).to.be.false;
+ });
+ });
+}
+
+module.exports = {
+ shouldBehaveLikeSet,
+};
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.test.js
new file mode 100644
index 000000000..66d666058
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/EnumerableSet.test.js
@@ -0,0 +1,61 @@
+const { ethers } = require('hardhat');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { mapValues } = require('../../helpers/iterate');
+const { generators } = require('../../helpers/random');
+const { TYPES } = require('../../../scripts/generate/templates/EnumerableSet.opts');
+
+const { shouldBehaveLikeSet } = require('./EnumerableSet.behavior');
+
+const getMethods = (mock, fnSigs) => {
+ return mapValues(
+ fnSigs,
+ fnSig =>
+ (...args) =>
+ mock.getFunction(fnSig)(0, ...args),
+ );
+};
+
+async function fixture() {
+ const mock = await ethers.deployContract('$EnumerableSet');
+
+ const env = Object.fromEntries(
+ TYPES.map(({ name, type }) => [
+ type,
+ {
+ values: Array.from({ length: 3 }, generators[type]),
+ methods: getMethods(mock, {
+ add: `$add(uint256,${type})`,
+ remove: `$remove(uint256,${type})`,
+ contains: `$contains(uint256,${type})`,
+ length: `$length_EnumerableSet_${name}(uint256)`,
+ at: `$at_EnumerableSet_${name}(uint256,uint256)`,
+ values: `$values_EnumerableSet_${name}(uint256)`,
+ }),
+ events: {
+ addReturn: `return$add_EnumerableSet_${name}_${type}`,
+ removeReturn: `return$remove_EnumerableSet_${name}_${type}`,
+ },
+ },
+ ]),
+ );
+
+ return { mock, env };
+}
+
+describe('EnumerableSet', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ for (const { type } of TYPES) {
+ describe(type, function () {
+ beforeEach(function () {
+ Object.assign(this, this.env[type]);
+ [this.valueA, this.valueB, this.valueC] = this.values;
+ });
+
+ shouldBehaveLikeSet();
+ });
+ }
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Heap.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Heap.t.sol
new file mode 100644
index 000000000..434f37f66
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Heap.t.sol
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Test} from "forge-std/Test.sol";
+import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
+import {Heap} from "@openzeppelin/contracts/utils/structs/Heap.sol";
+import {Comparators} from "@openzeppelin/contracts/utils/Comparators.sol";
+
+contract Uint256HeapTest is Test {
+ using Heap for Heap.Uint256Heap;
+
+ Heap.Uint256Heap internal heap;
+
+ function _validateHeap(function(uint256, uint256) view returns (bool) comp) internal {
+ for (uint32 i = 1; i < heap.length(); ++i) {
+ assertFalse(comp(heap.tree[i], heap.tree[(i - 1) / 2]));
+ }
+ }
+
+ function testFuzz(uint256[] calldata input) public {
+ vm.assume(input.length < 0x20);
+ assertEq(heap.length(), 0);
+
+ uint256 min = type(uint256).max;
+ for (uint256 i = 0; i < input.length; ++i) {
+ heap.insert(input[i]);
+ assertEq(heap.length(), i + 1);
+ _validateHeap(Comparators.lt);
+
+ min = Math.min(min, input[i]);
+ assertEq(heap.peek(), min);
+ }
+
+ uint256 max = 0;
+ for (uint256 i = 0; i < input.length; ++i) {
+ uint256 top = heap.peek();
+ uint256 pop = heap.pop();
+ assertEq(heap.length(), input.length - i - 1);
+ _validateHeap(Comparators.lt);
+
+ assertEq(pop, top);
+ assertGe(pop, max);
+ max = pop;
+ }
+ }
+
+ function testFuzzGt(uint256[] calldata input) public {
+ vm.assume(input.length < 0x20);
+ assertEq(heap.length(), 0);
+
+ uint256 max = 0;
+ for (uint256 i = 0; i < input.length; ++i) {
+ heap.insert(input[i], Comparators.gt);
+ assertEq(heap.length(), i + 1);
+ _validateHeap(Comparators.gt);
+
+ max = Math.max(max, input[i]);
+ assertEq(heap.peek(), max);
+ }
+
+ uint256 min = type(uint256).max;
+ for (uint256 i = 0; i < input.length; ++i) {
+ uint256 top = heap.peek();
+ uint256 pop = heap.pop(Comparators.gt);
+ assertEq(heap.length(), input.length - i - 1);
+ _validateHeap(Comparators.gt);
+
+ assertEq(pop, top);
+ assertLe(pop, min);
+ min = pop;
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Heap.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Heap.test.js
new file mode 100644
index 000000000..6d751205c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/Heap.test.js
@@ -0,0 +1,113 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Heap');
+ return { mock };
+}
+
+describe('Heap', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('Uint256Heap', function () {
+ it('starts empty', async function () {
+ expect(await this.mock.$length(0)).to.equal(0n);
+ });
+
+ it('peek, pop and replace from empty', async function () {
+ await expect(this.mock.$peek(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ await expect(this.mock.$pop(0)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ await expect(this.mock.$replace(0, 0n)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ });
+
+ it('clear', async function () {
+ await this.mock.$insert(0, 42n);
+
+ expect(await this.mock.$length(0)).to.equal(1n);
+ expect(await this.mock.$peek(0)).to.equal(42n);
+
+ await this.mock.$clear(0);
+
+ expect(await this.mock.$length(0)).to.equal(0n);
+ await expect(this.mock.$peek(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ });
+
+ it('support duplicated items', async function () {
+ expect(await this.mock.$length(0)).to.equal(0n);
+
+ // insert 5 times
+ await this.mock.$insert(0, 42n);
+ await this.mock.$insert(0, 42n);
+ await this.mock.$insert(0, 42n);
+ await this.mock.$insert(0, 42n);
+ await this.mock.$insert(0, 42n);
+
+ // pop 5 times
+ await expect(this.mock.$pop(0)).to.emit(this.mock, 'return$pop').withArgs(42n);
+ await expect(this.mock.$pop(0)).to.emit(this.mock, 'return$pop').withArgs(42n);
+ await expect(this.mock.$pop(0)).to.emit(this.mock, 'return$pop').withArgs(42n);
+ await expect(this.mock.$pop(0)).to.emit(this.mock, 'return$pop').withArgs(42n);
+ await expect(this.mock.$pop(0)).to.emit(this.mock, 'return$pop').withArgs(42n);
+
+ // popping a 6th time panics
+ await expect(this.mock.$pop(0)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ });
+
+ it('insert, pop and replace', async function () {
+ const heap = [];
+ for (const { op, value } of [
+ { op: 'insert', value: 712 }, // [712]
+ { op: 'insert', value: 20 }, // [20, 712]
+ { op: 'insert', value: 4337 }, // [20, 712, 4437]
+ { op: 'pop' }, // 20, [712, 4437]
+ { op: 'insert', value: 1559 }, // [712, 1559, 4437]
+ { op: 'insert', value: 165 }, // [165, 712, 1559, 4437]
+ { op: 'insert', value: 155 }, // [155, 165, 712, 1559, 4437]
+ { op: 'insert', value: 7702 }, // [155, 165, 712, 1559, 4437, 7702]
+ { op: 'pop' }, // 155, [165, 712, 1559, 4437, 7702]
+ { op: 'replace', value: 721 }, // 165, [712, 721, 1559, 4437, 7702]
+ { op: 'pop' }, // 712, [721, 1559, 4437, 7702]
+ { op: 'pop' }, // 721, [1559, 4437, 7702]
+ { op: 'pop' }, // 1559, [4437, 7702]
+ { op: 'pop' }, // 4437, [7702]
+ { op: 'pop' }, // 7702, []
+ { op: 'pop' }, // panic
+ { op: 'replace', value: '1363' }, // panic
+ ]) {
+ switch (op) {
+ case 'insert':
+ await this.mock.$insert(0, value);
+ heap.push(value);
+ heap.sort((a, b) => a - b);
+ break;
+ case 'pop':
+ if (heap.length == 0) {
+ await expect(this.mock.$pop(0)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ } else {
+ await expect(this.mock.$pop(0)).to.emit(this.mock, 'return$pop').withArgs(heap.shift());
+ }
+ break;
+ case 'replace':
+ if (heap.length == 0) {
+ await expect(this.mock.$replace(0, value)).to.be.revertedWithPanic(PANIC_CODES.POP_ON_EMPTY_ARRAY);
+ } else {
+ await expect(this.mock.$replace(0, value)).to.emit(this.mock, 'return$replace').withArgs(heap.shift());
+ heap.push(value);
+ heap.sort((a, b) => a - b);
+ }
+ break;
+ }
+ expect(await this.mock.$length(0)).to.equal(heap.length);
+ if (heap.length == 0) {
+ await expect(this.mock.$peek(0)).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS);
+ } else {
+ expect(await this.mock.$peek(0)).to.equal(heap[0]);
+ }
+ }
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/MerkleTree.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/MerkleTree.test.js
new file mode 100644
index 000000000..bec39ceea
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/structs/MerkleTree.test.js
@@ -0,0 +1,100 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+const { PANIC_CODES } = require('@nomicfoundation/hardhat-chai-matchers/panic');
+const { StandardMerkleTree } = require('@openzeppelin/merkle-tree');
+
+const { generators } = require('../../helpers/random');
+
+const makeTree = (leaves = [ethers.ZeroHash]) =>
+ StandardMerkleTree.of(
+ leaves.map(leaf => [leaf]),
+ ['bytes32'],
+ { sortLeaves: false },
+ );
+
+const hashLeaf = leaf => makeTree().leafHash([leaf]);
+
+const DEPTH = 4n; // 16 slots
+const ZERO = hashLeaf(ethers.ZeroHash);
+
+async function fixture() {
+ const mock = await ethers.deployContract('MerkleTreeMock');
+ await mock.setup(DEPTH, ZERO);
+ return { mock };
+}
+
+describe('MerkleTree', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ it('sets initial values at setup', async function () {
+ const merkleTree = makeTree(Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash));
+
+ expect(await this.mock.root()).to.equal(merkleTree.root);
+ expect(await this.mock.depth()).to.equal(DEPTH);
+ expect(await this.mock.nextLeafIndex()).to.equal(0n);
+ });
+
+ describe('push', function () {
+ it('tree is correctly updated', async function () {
+ const leaves = Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash);
+
+ // for each leaf slot
+ for (const i in leaves) {
+ // generate random leaf and hash it
+ const hashedLeaf = hashLeaf((leaves[i] = generators.bytes32()));
+
+ // update leaf list and rebuild tree.
+ const tree = makeTree(leaves);
+
+ // push value to tree
+ await expect(this.mock.push(hashedLeaf)).to.emit(this.mock, 'LeafInserted').withArgs(hashedLeaf, i, tree.root);
+
+ // check tree
+ expect(await this.mock.root()).to.equal(tree.root);
+ expect(await this.mock.nextLeafIndex()).to.equal(BigInt(i) + 1n);
+ }
+ });
+
+ it('revert when tree is full', async function () {
+ await Promise.all(Array.from({ length: 2 ** Number(DEPTH) }).map(() => this.mock.push(ethers.ZeroHash)));
+
+ await expect(this.mock.push(ethers.ZeroHash)).to.be.revertedWithPanic(PANIC_CODES.TOO_MUCH_MEMORY_ALLOCATED);
+ });
+ });
+
+ it('reset', async function () {
+ // empty tree
+ const zeroLeaves = Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash);
+ const zeroTree = makeTree(zeroLeaves);
+
+ // tree with one element
+ const leaves = Array.from({ length: 2 ** Number(DEPTH) }, () => ethers.ZeroHash);
+ const hashedLeaf = hashLeaf((leaves[0] = generators.bytes32())); // fill first leaf and hash it
+ const tree = makeTree(leaves);
+
+ // root should be that of a zero tree
+ expect(await this.mock.root()).to.equal(zeroTree.root);
+ expect(await this.mock.nextLeafIndex()).to.equal(0n);
+
+ // push leaf and check root
+ await expect(this.mock.push(hashedLeaf)).to.emit(this.mock, 'LeafInserted').withArgs(hashedLeaf, 0, tree.root);
+
+ expect(await this.mock.root()).to.equal(tree.root);
+ expect(await this.mock.nextLeafIndex()).to.equal(1n);
+
+ // reset tree
+ await this.mock.setup(DEPTH, ZERO);
+
+ expect(await this.mock.root()).to.equal(zeroTree.root);
+ expect(await this.mock.nextLeafIndex()).to.equal(0n);
+
+ // re-push leaf and check root
+ await expect(this.mock.push(hashedLeaf)).to.emit(this.mock, 'LeafInserted').withArgs(hashedLeaf, 0, tree.root);
+
+ expect(await this.mock.root()).to.equal(tree.root);
+ expect(await this.mock.nextLeafIndex()).to.equal(1n);
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/types/Time.test.js b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/types/Time.test.js
new file mode 100644
index 000000000..3ab6fefa8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/lib/openzeppelin-contracts/test/utils/types/Time.test.js
@@ -0,0 +1,135 @@
+const { ethers } = require('hardhat');
+const { expect } = require('chai');
+const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
+
+const { product } = require('../../helpers/iterate');
+const { max } = require('../../helpers/math');
+const time = require('../../helpers/time');
+
+const MAX_UINT32 = 1n << (32n - 1n);
+const MAX_UINT48 = 1n << (48n - 1n);
+const SOME_VALUES = [0n, 1n, 2n, 15n, 16n, 17n, 42n];
+
+const asUint = (value, size) => {
+ value = ethers.toBigInt(value);
+ size = ethers.toBigInt(size);
+ expect(value).to.be.greaterThanOrEqual(0n, `value is not a valid uint${size}`);
+ expect(value).to.be.lessThan(1n << size, `value is not a valid uint${size}`);
+ return value;
+};
+
+const unpackDelay = delay => ({
+ valueBefore: (asUint(delay, 112) >> 32n) % (1n << 32n),
+ valueAfter: (asUint(delay, 112) >> 0n) % (1n << 32n),
+ effect: (asUint(delay, 112) >> 64n) % (1n << 48n),
+});
+
+const packDelay = ({ valueBefore, valueAfter = 0n, effect = 0n }) =>
+ (asUint(valueAfter, 32) << 0n) + (asUint(valueBefore, 32) << 32n) + (asUint(effect, 48) << 64n);
+
+const effectSamplesForTimepoint = timepoint => [
+ 0n,
+ timepoint,
+ ...product([-1n, 1n], [1n, 2n, 17n, 42n])
+ .map(([sign, shift]) => timepoint + sign * shift)
+ .filter(effect => effect > 0n && effect <= MAX_UINT48),
+ MAX_UINT48,
+];
+
+async function fixture() {
+ const mock = await ethers.deployContract('$Time');
+ return { mock };
+}
+
+describe('Time', function () {
+ beforeEach(async function () {
+ Object.assign(this, await loadFixture(fixture));
+ });
+
+ describe('clocks', function () {
+ it('timestamp', async function () {
+ expect(await this.mock.$timestamp()).to.equal(await time.clock.timestamp());
+ });
+
+ it('block number', async function () {
+ expect(await this.mock.$blockNumber()).to.equal(await time.clock.blocknumber());
+ });
+ });
+
+ describe('Delay', function () {
+ describe('packing and unpacking', function () {
+ const valueBefore = 17n;
+ const valueAfter = 42n;
+ const effect = 69n;
+ const delay = 1272825341158973505578n;
+
+ it('pack', async function () {
+ expect(await this.mock.$pack(valueBefore, valueAfter, effect)).to.equal(delay);
+ expect(packDelay({ valueBefore, valueAfter, effect })).to.equal(delay);
+ });
+
+ it('unpack', async function () {
+ expect(await this.mock.$unpack(delay)).to.deep.equal([valueBefore, valueAfter, effect]);
+
+ expect(unpackDelay(delay)).to.deep.equal({
+ valueBefore,
+ valueAfter,
+ effect,
+ });
+ });
+ });
+
+ it('toDelay', async function () {
+ for (const value of [...SOME_VALUES, MAX_UINT32]) {
+ expect(await this.mock.$toDelay(value).then(unpackDelay)).to.deep.equal({
+ valueBefore: 0n,
+ valueAfter: value,
+ effect: 0n,
+ });
+ }
+ });
+
+ it('get & getFull', async function () {
+ const timepoint = await time.clock.timestamp();
+ const valueBefore = 24194n;
+ const valueAfter = 4214143n;
+
+ for (const effect of effectSamplesForTimepoint(timepoint)) {
+ const isPast = effect <= timepoint;
+ const delay = packDelay({ valueBefore, valueAfter, effect });
+
+ expect(await this.mock.$get(delay)).to.equal(isPast ? valueAfter : valueBefore);
+ expect(await this.mock.$getFull(delay)).to.deep.equal([
+ isPast ? valueAfter : valueBefore,
+ isPast ? 0n : valueAfter,
+ isPast ? 0n : effect,
+ ]);
+ }
+ });
+
+ it('withUpdate', async function () {
+ const timepoint = await time.clock.timestamp();
+ const valueBefore = 24194n;
+ const valueAfter = 4214143n;
+ const newvalueAfter = 94716n;
+
+ for (const effect of effectSamplesForTimepoint(timepoint))
+ for (const minSetback of [...SOME_VALUES, MAX_UINT32]) {
+ const isPast = effect <= timepoint;
+ const expectedvalueBefore = isPast ? valueAfter : valueBefore;
+ const expectedSetback = max(minSetback, expectedvalueBefore - newvalueAfter, 0n);
+
+ expect(
+ await this.mock.$withUpdate(packDelay({ valueBefore, valueAfter, effect }), newvalueAfter, minSetback),
+ ).to.deep.equal([
+ packDelay({
+ valueBefore: expectedvalueBefore,
+ valueAfter: newvalueAfter,
+ effect: timepoint + expectedSetback,
+ }),
+ timepoint + expectedSetback,
+ ]);
+ }
+ });
+ });
+});
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/package.json b/lib/signals-implicit-mode/lib/sequence-v3/package.json
new file mode 100644
index 000000000..eae9d3ef8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/package.json
@@ -0,0 +1,13 @@
+{
+ "devDependencies": {
+ "lefthook": "^1.6.1",
+ "prettier": "^3.2.5"
+ },
+ "scripts": {
+ "postinstall": "lefthook install",
+ "format:prettier": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml}\"",
+ "format:forge": "forge fmt",
+ "test": "forge test",
+ "coverage": "forge coverage --no-match-coverage \"(script|test)\""
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/pnpm-lock.yaml b/lib/signals-implicit-mode/lib/sequence-v3/pnpm-lock.yaml
new file mode 100644
index 000000000..caff6c479
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/pnpm-lock.yaml
@@ -0,0 +1,157 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+ .:
+ devDependencies:
+ lefthook:
+ specifier: ^1.6.1
+ version: 1.10.8
+ prettier:
+ specifier: ^3.2.5
+ version: 3.4.2
+
+packages:
+ lefthook-darwin-arm64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-uE5oLjWuANaAyv6KQoWWGacZgKq5zGd3UmkWLE2OSSrZbgSdTz1R6Uios2yMXrGDptBX9PDWp9SNcHPhEoQlNw==,
+ }
+ cpu: [arm64]
+ os: [darwin]
+
+ lefthook-darwin-x64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-502vfNdfJIDxLQKtlS3TbnM54PrV5wcssVvbDEnkLLjyrEImOZ3lVz3cqrT42KvFYFqgarrhII9jigqUxnLuSQ==,
+ }
+ cpu: [x64]
+ os: [darwin]
+
+ lefthook-freebsd-arm64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-xkqxIxEnFK9zyN3F3Lc11/byuYAR5z7FJBH5UTb2Wnxob7BwYfB0gXBcw3gKEYZiwHFNlyJQimndc7QWZ7y4kw==,
+ }
+ cpu: [arm64]
+ os: [freebsd]
+
+ lefthook-freebsd-x64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-hCErafcyykVCIMb/6hzredNQ1ogDcz07lphf0k0eGUbr94XK7IUOkQwD++XOAijOHknkzS1V9WvjV1lrhGYtUA==,
+ }
+ cpu: [x64]
+ os: [freebsd]
+
+ lefthook-linux-arm64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-YFqT/hj+nzTTwzaDSdmYGKvpZI6/Wt3Id6+6gEU8VMAojXOe9rWAXitfoiDXW1TNPzpHqwyGnjOCcjquF1umkw==,
+ }
+ cpu: [arm64]
+ os: [linux]
+
+ lefthook-linux-x64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-nOARm1gE0EeMSEHaulpFDPnIqlQFPsFnaSkmCK2gWXG5jBbRtMr4BcJLDPzsekDKxskr5mZwlPQ2fFW3B/jiCA==,
+ }
+ cpu: [x64]
+ os: [linux]
+
+ lefthook-openbsd-arm64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-6cUokm4Dd5OMNewVWIV9bM+nebBOrImCAOjbdfCEW4hhtIRvr6XZirHu0BVJM/I5Ed0MjiAme+L6yV7LW68HAA==,
+ }
+ cpu: [arm64]
+ os: [openbsd]
+
+ lefthook-openbsd-x64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-659TblZOM7pV9ImSRjpMQSynA5L1DTcoS37TJN7Y/84O3pXhKYAN1Lm5EJFZQ1dBMEJDeAD/L1V98RWqnFx/gw==,
+ }
+ cpu: [x64]
+ os: [openbsd]
+
+ lefthook-windows-arm64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-g5O44F+Mo0n2RzXL7A9g0TM5VA60OWWw7CPNLi42qOniv1t6/43glxB7bmKalrLAznFR5UbyiLMmO6ospDXctg==,
+ }
+ cpu: [arm64]
+ os: [win32]
+
+ lefthook-windows-x64@1.10.8:
+ resolution:
+ {
+ integrity: sha512-PZ72IXi29MdOCNZZvqRrBONMfe4DZU3GVowotLfHo4U/1oTTd2LImJitm0qbFjf9kCtRHLkD4K/l7ZgV4gsxtA==,
+ }
+ cpu: [x64]
+ os: [win32]
+
+ lefthook@1.10.8:
+ resolution:
+ {
+ integrity: sha512-yJM97cNPH7zYbLUJ8G2LGhJbSRd66mv5BVeryLiEsmXER3vz4wGtiLJEYRwveSEZetOMBgAlVBIZEfuxJGsjIA==,
+ }
+ hasBin: true
+
+ prettier@3.4.2:
+ resolution:
+ {
+ integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==,
+ }
+ engines: { node: '>=14' }
+ hasBin: true
+
+snapshots:
+ lefthook-darwin-arm64@1.10.8:
+ optional: true
+
+ lefthook-darwin-x64@1.10.8:
+ optional: true
+
+ lefthook-freebsd-arm64@1.10.8:
+ optional: true
+
+ lefthook-freebsd-x64@1.10.8:
+ optional: true
+
+ lefthook-linux-arm64@1.10.8:
+ optional: true
+
+ lefthook-linux-x64@1.10.8:
+ optional: true
+
+ lefthook-openbsd-arm64@1.10.8:
+ optional: true
+
+ lefthook-openbsd-x64@1.10.8:
+ optional: true
+
+ lefthook-windows-arm64@1.10.8:
+ optional: true
+
+ lefthook-windows-x64@1.10.8:
+ optional: true
+
+ lefthook@1.10.8:
+ optionalDependencies:
+ lefthook-darwin-arm64: 1.10.8
+ lefthook-darwin-x64: 1.10.8
+ lefthook-freebsd-arm64: 1.10.8
+ lefthook-freebsd-x64: 1.10.8
+ lefthook-linux-arm64: 1.10.8
+ lefthook-linux-x64: 1.10.8
+ lefthook-openbsd-arm64: 1.10.8
+ lefthook-openbsd-x64: 1.10.8
+ lefthook-windows-arm64: 1.10.8
+ lefthook-windows-x64: 1.10.8
+
+ prettier@3.4.2: {}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/pnpm-workspace.yaml b/lib/signals-implicit-mode/lib/sequence-v3/pnpm-workspace.yaml
new file mode 100644
index 000000000..e7a00fbdc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+packages:
+ - 'sdk/*'
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/script/Deploy.s.sol b/lib/signals-implicit-mode/lib/sequence-v3/script/Deploy.s.sol
new file mode 100644
index 000000000..2b3bec19f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/script/Deploy.s.sol
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { SingletonDeployer, console } from "lib/erc2470-libs/script/SingletonDeployer.s.sol";
+import { Factory } from "src/Factory.sol";
+import { Guest } from "src/Guest.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { SessionManager } from "src/extensions/sessions/SessionManager.sol";
+
+contract Deploy is SingletonDeployer {
+
+ function run() external {
+ uint256 pk = vm.envUint("PRIVATE_KEY");
+ address entryPoint = vm.envAddress("ERC4337_ENTRY_POINT_V7");
+ if (entryPoint == address(0)) {
+ entryPoint = 0x0000000071727De22E5E9d8BAf0edAc6f37da032;
+ }
+
+ bytes32 salt = bytes32(0);
+
+ bytes memory initCode = abi.encodePacked(type(Factory).creationCode);
+ address factory = _deployIfNotAlready("Factory", initCode, salt, pk);
+
+ initCode = abi.encodePacked(type(Stage1Module).creationCode, abi.encode(factory, entryPoint));
+ address stage1Module = _deployIfNotAlready("Stage1Module", initCode, salt, pk);
+
+ console.log("Stage2Module for Stage1Module is", Stage1Module(payable(stage1Module)).STAGE_2_IMPLEMENTATION());
+
+ initCode = abi.encodePacked(type(Guest).creationCode);
+ _deployIfNotAlready("Guest", initCode, salt, pk);
+
+ initCode = abi.encodePacked(type(SessionManager).creationCode);
+ _deployIfNotAlready("SessionManager", initCode, salt, pk);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/script/DeployMocks.s.sol b/lib/signals-implicit-mode/lib/sequence-v3/script/DeployMocks.s.sol
new file mode 100644
index 000000000..a3486687c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/script/DeployMocks.s.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { SingletonDeployer, console } from "lib/erc2470-libs/script/SingletonDeployer.s.sol";
+
+import { Emitter } from "test/mocks/Emitter.sol";
+
+contract DeployMocks is SingletonDeployer {
+
+ function run() external {
+ uint256 pk = vm.envUint("PRIVATE_KEY");
+
+ bytes32 salt = bytes32(0);
+
+ bytes memory initCode = abi.encodePacked(type(Emitter).creationCode);
+ _deployIfNotAlready("Emitter", initCode, salt, pk);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Estimator.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Estimator.sol
new file mode 100644
index 000000000..a67b8b588
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Estimator.sol
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Stage2Module } from "./Stage2Module.sol";
+
+import { Payload } from "./modules/Payload.sol";
+import { IDelegatedExtension } from "./modules/interfaces/IDelegatedExtension.sol";
+import { LibOptim } from "./utils/LibOptim.sol";
+
+/// @title Estimator
+/// @author William Hua
+/// @notice Helper for estimating the gas used for payload validation and execution
+contract Estimator is Stage2Module {
+
+ constructor(
+ address _entryPoint
+ ) Stage2Module(_entryPoint) { }
+
+ function _isValidImage(
+ bytes32 _imageHash
+ ) internal view virtual override returns (bool) {
+ super._isValidImage(_imageHash);
+ return true;
+ }
+
+ /// @notice Estimate the gas used for payload validation and execution
+ /// @param _payload The payload to estimate the gas used for
+ /// @param _signature The signature to validate the payload with
+ /// @return gasUsed The gas used for payload validation and execution
+ function estimate(
+ bytes calldata _payload,
+ bytes calldata _signature
+ ) external payable virtual returns (uint256 gasUsed) {
+ uint256 startingGas = gasleft();
+ Payload.Decoded memory decoded = Payload.fromPackedCalls(_payload);
+
+ _consumeNonce(decoded.space, readNonce(decoded.space));
+ (bool isValid, bytes32 opHash) = signatureValidation(decoded, _signature);
+
+ if (!isValid) {
+ revert InvalidSignature(decoded, _signature);
+ }
+
+ _estimate(startingGas, opHash, decoded);
+
+ return startingGas - gasleft();
+ }
+
+ function _estimate(uint256 _startingGas, bytes32 _opHash, Payload.Decoded memory _decoded) private {
+ bool errorFlag = false;
+
+ uint256 numCalls = _decoded.calls.length;
+ for (uint256 i = 0; i < numCalls; i++) {
+ Payload.Call memory call = _decoded.calls[i];
+
+ // Skip onlyFallback calls if no error occurred
+ if (call.onlyFallback && !errorFlag) {
+ emit CallSkipped(_opHash, i);
+ continue;
+ }
+
+ // Reset the error flag
+ // onlyFallback calls only apply when the immediately preceding transaction fails
+ errorFlag = false;
+
+ uint256 gasLimit = call.gasLimit;
+ if (gasLimit != 0 && gasleft() < gasLimit) {
+ revert NotEnoughGas(_decoded, i, gasleft());
+ }
+
+ bool success;
+ if (call.delegateCall) {
+ (success) = LibOptim.delegatecall(
+ call.to,
+ gasLimit == 0 ? gasleft() : gasLimit,
+ abi.encodeWithSelector(
+ IDelegatedExtension.handleSequenceDelegateCall.selector,
+ _opHash,
+ _startingGas,
+ i,
+ numCalls,
+ _decoded.space,
+ call.data
+ )
+ );
+ } else {
+ (success) = LibOptim.call(call.to, call.value, gasLimit == 0 ? gasleft() : gasLimit, call.data);
+ }
+
+ if (!success) {
+ if (call.behaviorOnError == Payload.BEHAVIOR_IGNORE_ERROR) {
+ errorFlag = true;
+ emit CallFailed(_opHash, i, LibOptim.returnData());
+ continue;
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_REVERT_ON_ERROR) {
+ revert Reverted(_decoded, i, LibOptim.returnData());
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_ABORT_ON_ERROR) {
+ emit CallAborted(_opHash, i, LibOptim.returnData());
+ break;
+ }
+ }
+
+ emit CallSucceeded(_opHash, i);
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Factory.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Factory.sol
new file mode 100644
index 000000000..04a2277fa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Factory.sol
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import "./Wallet.sol";
+
+/// @title Factory
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Factory for deploying wallets
+contract Factory {
+
+ /// @notice Error thrown when the deployment fails
+ error DeployFailed(address _mainModule, bytes32 _salt);
+
+ /// @notice Deploy a new wallet instance
+ /// @param _mainModule Address of the main module to be used by the wallet
+ /// @param _salt Salt used to generate the wallet, which is the imageHash of the wallet's configuration.
+ /// @dev It is recommended to not have more than 200 signers as opcode repricing could make transactions impossible to execute as all the signers must be passed for each transaction.
+ function deploy(address _mainModule, bytes32 _salt) public payable returns (address _contract) {
+ bytes memory code = abi.encodePacked(Wallet.creationCode, uint256(uint160(_mainModule)));
+ assembly {
+ _contract := create2(callvalue(), add(code, 32), mload(code), _salt)
+ }
+ if (_contract == address(0)) {
+ revert DeployFailed(_mainModule, _salt);
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Guest.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Guest.sol
new file mode 100644
index 000000000..0f157b1df
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Guest.sol
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Calls } from "./modules/Calls.sol";
+import { Payload } from "./modules/Payload.sol";
+
+import { LibBytes } from "./utils/LibBytes.sol";
+import { LibOptim } from "./utils/LibOptim.sol";
+
+/// @title Guest
+/// @author Agustin Aguilar, William Hua, Michael Standen
+/// @notice Guest for dispatching calls
+contract Guest {
+
+ using LibBytes for bytes;
+
+ /// @notice Error thrown when a delegate call is not allowed
+ error DelegateCallNotAllowed(uint256 index);
+
+ /// @notice Fallback function
+ /// @dev Dispatches the guest call
+ fallback() external payable {
+ Payload.Decoded memory decoded = Payload.fromPackedCalls(msg.data);
+ bytes32 opHash = Payload.hash(decoded);
+ _dispatchGuest(decoded, opHash);
+ }
+
+ function _dispatchGuest(Payload.Decoded memory _decoded, bytes32 _opHash) internal {
+ bool errorFlag = false;
+
+ uint256 numCalls = _decoded.calls.length;
+ for (uint256 i = 0; i < numCalls; i++) {
+ Payload.Call memory call = _decoded.calls[i];
+
+ // Skip onlyFallback calls if no error occurred
+ if (call.onlyFallback && !errorFlag) {
+ emit Calls.CallSkipped(_opHash, i);
+ continue;
+ }
+
+ // Reset the error flag
+ // onlyFallback calls only apply when the immediately preceding transaction fails
+ errorFlag = false;
+
+ uint256 gasLimit = call.gasLimit;
+ if (gasLimit != 0 && gasleft() < gasLimit) {
+ revert Calls.NotEnoughGas(_decoded, i, gasleft());
+ }
+
+ if (call.delegateCall) {
+ revert DelegateCallNotAllowed(i);
+ }
+
+ bool success = LibOptim.call(call.to, call.value, gasLimit == 0 ? gasleft() : gasLimit, call.data);
+ if (!success) {
+ if (call.behaviorOnError == Payload.BEHAVIOR_IGNORE_ERROR) {
+ errorFlag = true;
+ emit Calls.CallFailed(_opHash, i, LibOptim.returnData());
+ continue;
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_REVERT_ON_ERROR) {
+ revert Calls.Reverted(_decoded, i, LibOptim.returnData());
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_ABORT_ON_ERROR) {
+ emit Calls.CallAborted(_opHash, i, LibOptim.returnData());
+ break;
+ }
+ }
+
+ emit Calls.CallSucceeded(_opHash, i);
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Simulator.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Simulator.sol
new file mode 100644
index 000000000..8bc4b7ece
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Simulator.sol
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Stage2Module } from "./Stage2Module.sol";
+
+import { Payload } from "./modules/Payload.sol";
+import { IDelegatedExtension } from "./modules/interfaces/IDelegatedExtension.sol";
+import { LibOptim } from "./utils/LibOptim.sol";
+
+/// @title Simulator
+/// @author William Hua
+/// @notice Helper for simulating the execution of a payload
+contract Simulator is Stage2Module {
+
+ constructor(
+ address _entryPoint
+ ) Stage2Module(_entryPoint) { }
+
+ /// @notice Status of the call
+ enum Status {
+ Skipped,
+ Succeeded,
+ Failed,
+ Aborted,
+ Reverted,
+ NotEnoughGas
+ }
+
+ /// @notice Result of the call
+ struct Result {
+ Status status;
+ bytes result;
+ uint256 gasUsed;
+ }
+
+ /// @notice Simulate the execution of a payload
+ /// @param _calls The calls to simulate
+ /// @return results The results of the calls
+ function simulate(
+ Payload.Call[] calldata _calls
+ ) external returns (Result[] memory results) {
+ uint256 startingGas = gasleft();
+ bool errorFlag = false;
+
+ uint256 numCalls = _calls.length;
+ results = new Result[](numCalls);
+ for (uint256 i = 0; i < numCalls; i++) {
+ Payload.Call memory call = _calls[i];
+
+ // Skip onlyFallback calls if no error occurred
+ if (call.onlyFallback && !errorFlag) {
+ continue;
+ }
+
+ // Reset the error flag
+ // onlyFallback calls only apply when the immediately preceding transaction fails
+ errorFlag = false;
+
+ uint256 gasLimit = call.gasLimit;
+ if (gasLimit != 0 && gasleft() < gasLimit) {
+ results[i].status = Status.NotEnoughGas;
+ results[i].result = abi.encode(gasleft());
+ return results;
+ }
+
+ bool success;
+ if (call.delegateCall) {
+ uint256 initial = gasleft();
+ (success) = LibOptim.delegatecall(
+ call.to,
+ gasLimit == 0 ? gasleft() : gasLimit,
+ abi.encodeWithSelector(
+ IDelegatedExtension.handleSequenceDelegateCall.selector, 0, startingGas, i, numCalls, 0, call.data
+ )
+ );
+ results[i].gasUsed = initial - gasleft();
+ } else {
+ uint256 initial = gasleft();
+ (success) = LibOptim.call(call.to, call.value, gasLimit == 0 ? gasleft() : gasLimit, call.data);
+ results[i].gasUsed = initial - gasleft();
+ }
+
+ if (!success) {
+ if (call.behaviorOnError == Payload.BEHAVIOR_IGNORE_ERROR) {
+ errorFlag = true;
+ results[i].status = Status.Failed;
+ results[i].result = LibOptim.returnData();
+ continue;
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_REVERT_ON_ERROR) {
+ results[i].status = Status.Reverted;
+ results[i].result = LibOptim.returnData();
+ return results;
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_ABORT_ON_ERROR) {
+ results[i].status = Status.Aborted;
+ results[i].result = LibOptim.returnData();
+ break;
+ }
+ }
+
+ results[i].status = Status.Succeeded;
+ results[i].result = LibOptim.returnData();
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Stage1Module.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Stage1Module.sol
new file mode 100644
index 000000000..bbd8b2df8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Stage1Module.sol
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Stage2Module } from "./Stage2Module.sol";
+import { Calls } from "./modules/Calls.sol";
+
+import { ERC4337v07 } from "./modules/ERC4337v07.sol";
+import { Hooks } from "./modules/Hooks.sol";
+import { Stage1Auth } from "./modules/auth/Stage1Auth.sol";
+import { IAuth } from "./modules/interfaces/IAuth.sol";
+
+/// @title Stage1Module
+/// @author Agustin Aguilar
+/// @notice The initial stage of the wallet
+contract Stage1Module is Calls, Stage1Auth, Hooks, ERC4337v07 {
+
+ constructor(
+ address _factory,
+ address _entryPoint
+ ) Stage1Auth(_factory, address(new Stage2Module(_entryPoint))) ERC4337v07(_entryPoint) { }
+
+ /// @inheritdoc IAuth
+ function _isValidImage(
+ bytes32 _imageHash
+ ) internal view virtual override(IAuth, Stage1Auth) returns (bool) {
+ return super._isValidImage(_imageHash);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Stage2Module.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Stage2Module.sol
new file mode 100644
index 000000000..d38d1a4b0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Stage2Module.sol
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Calls } from "./modules/Calls.sol";
+
+import { ERC4337v07 } from "./modules/ERC4337v07.sol";
+import { Hooks } from "./modules/Hooks.sol";
+import { Stage2Auth } from "./modules/auth/Stage2Auth.sol";
+import { IAuth } from "./modules/interfaces/IAuth.sol";
+
+/// @title Stage2Module
+/// @author Agustin Aguilar
+/// @notice The second stage of the wallet
+contract Stage2Module is Calls, Stage2Auth, Hooks, ERC4337v07 {
+
+ constructor(
+ address _entryPoint
+ ) ERC4337v07(_entryPoint) { }
+
+ /// @inheritdoc IAuth
+ function _isValidImage(
+ bytes32 _imageHash
+ ) internal view virtual override(IAuth, Stage2Auth) returns (bool) {
+ return super._isValidImage(_imageHash);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Wallet.huff b/lib/signals-implicit-mode/lib/sequence-v3/src/Wallet.huff
new file mode 100644
index 000000000..8e8e7908d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Wallet.huff
@@ -0,0 +1,55 @@
+// Delegate Proxy in Huff
+// @title Delegate Proxy
+// @notice Implements a proxy using the contract's own address to store the delegate target.
+// Calls with calldata (with or without ETH value) are forwarded to the stored target.
+// Calls sending only ETH without calldata do nothing and return immediately without forwarding.
+// @author Agusx1211
+#define macro CONSTRUCTOR() = takes (0) returns (0) {
+ 0x41 // [code + arg size] (code_size + 32)
+ __codeoffset(MAIN) // [code_start, code + arg size]
+ returndatasize // [0, code_start, code + arg size]
+ codecopy // []
+
+ __codesize(MAIN) // [code_size]
+ dup1 // [code_size, code_size]
+ mload // [arg1, code_size]
+ address // [address, arg1, code_size]
+ sstore // [code_size]
+
+ returndatasize // [0, code_size]
+ return
+}
+
+#define macro MAIN() = takes(0) returns(0) {
+ returndatasize // [0]
+ returndatasize // [0, 0]
+ calldatasize // [cs, 0, 0]
+ iszero // [cs == 0, 0, 0]
+ callvalue // [cv, cs == 0, 0, 0]
+ mul // [cv * cs == 0, 0, 0]
+ success // [nr, cv * cs == 0, 0, 0]
+ jumpi
+ calldatasize // [cds, 0, 0]
+ returndatasize // [0, cds, 0, 0]
+ returndatasize // [0, 0, cds, 0, 0]
+ calldatacopy // [0, 0]
+ returndatasize // [0, 0, 0]
+ calldatasize // [cds, 0, 0, 0]
+ returndatasize // [0, cds, 0, 0, 0]
+ address // [addr, 0, cds, 0, 0, 0]
+ sload // [imp, 0, cds, 0, 0, 0]
+ gas // [gas, imp, 0, cds, 0, 0, 0]
+ delegatecall // [suc, 0]
+ returndatasize // [rds, suc, 0]
+ dup3 // [0, rds, suc, 0]
+ dup1 // [0, 0, rds, suc, 0]
+ returndatacopy // [suc, 0]
+ swap1 // [0, suc]
+ returndatasize // [rds, 0, suc]
+ swap2 // [suc, 0, rds]
+ success // [nr, suc, 0, rds]
+ jumpi
+ revert
+ success:
+ return
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/Wallet.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/Wallet.sol
new file mode 100644
index 000000000..4f3822092
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/Wallet.sol
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.0;
+
+/*
+// Delegate Proxy in Huff
+// @title Delegate Proxy
+// @notice Implements a proxy using the contract's own address to store the delegate target.
+// Calls with calldata (with or without ETH value) are forwarded to the stored target.
+// Calls sending only ETH without calldata do nothing and return immediately without forwarding.
+// @author Agusx1211
+#define macro CONSTRUCTOR() = takes (0) returns (0) {
+ 0x41 // [code + arg size] (code_size + 32)
+ __codeoffset(MAIN) // [code_start, code + arg size]
+ returndatasize // [0, code_start, code + arg size]
+ codecopy // []
+
+ __codesize(MAIN) // [code_size]
+ dup1 // [code_size, code_size]
+ mload // [arg1, code_size]
+ address // [address, arg1, code_size]
+ sstore // [code_size]
+
+ returndatasize // [0, code_size]
+ return
+}
+
+#define macro MAIN() = takes(0) returns(0) {
+ returndatasize // [0]
+ returndatasize // [0, 0]
+ calldatasize // [cs, 0, 0]
+ iszero // [cs == 0, 0, 0]
+ callvalue // [cv, cs == 0, 0, 0]
+ mul // [cv * cs == 0, 0, 0]
+ success // [nr, cv * cs == 0, 0, 0]
+ jumpi
+ calldatasize // [cds, 0, 0]
+ returndatasize // [0, cds, 0, 0]
+ returndatasize // [0, 0, cds, 0, 0]
+ calldatacopy // [0, 0]
+ returndatasize // [0, 0, 0]
+ calldatasize // [cds, 0, 0, 0]
+ returndatasize // [0, cds, 0, 0, 0]
+ address // [addr, 0, cds, 0, 0, 0]
+ sload // [imp, 0, cds, 0, 0, 0]
+ gas // [gas, imp, 0, cds, 0, 0, 0]
+ delegatecall // [suc, 0]
+ returndatasize // [rds, suc, 0]
+ dup3 // [0, rds, suc, 0]
+ dup1 // [0, 0, rds, suc, 0]
+ returndatacopy // [suc, 0]
+ swap1 // [0, suc]
+ returndatasize // [rds, 0, suc]
+ swap2 // [suc, 0, rds]
+ success // [nr, suc, 0, rds]
+ jumpi
+ revert
+ success:
+ return
+}
+*/
+
+library Wallet {
+
+ bytes internal constant creationCode =
+ hex"6041600e3d396021805130553df33d3d36153402601f57363d3d373d363d30545af43d82803e903d91601f57fd5bf3";
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/passkeys/Passkeys.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/passkeys/Passkeys.sol
new file mode 100644
index 000000000..47a7b9842
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/passkeys/Passkeys.sol
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ISapientCompact } from "../../modules/interfaces/ISapient.sol";
+
+import { LibBytes } from "../../utils/LibBytes.sol";
+import { LibOptim } from "../../utils/LibOptim.sol";
+import { WebAuthn } from "../../utils/WebAuthn.sol";
+
+/// @title Passkeys
+/// @author Agustin Aguilar, Michael Standen
+/// @notice A sapient signer for passkeys
+contract Passkeys is ISapientCompact {
+
+ /// @notice Error thrown when the passkey signature is invalid
+ error InvalidPasskeySignature(
+ WebAuthn.WebAuthnAuth _webAuthnAuth, bool _requireUserVerification, bytes32 _x, bytes32 _y
+ );
+
+ function _rootForPasskey(
+ bool _requireUserVerification,
+ bytes32 _x,
+ bytes32 _y,
+ bytes32 _metadata
+ ) internal pure returns (bytes32) {
+ bytes32 a = LibOptim.fkeccak256(_x, _y);
+
+ bytes32 ruv;
+ assembly {
+ ruv := _requireUserVerification
+ }
+
+ bytes32 b = LibOptim.fkeccak256(ruv, _metadata);
+ return LibOptim.fkeccak256(a, b);
+ }
+
+ function _decodeSignature(
+ bytes calldata _signature
+ )
+ internal
+ pure
+ returns (
+ WebAuthn.WebAuthnAuth memory _webAuthnAuth,
+ bool _requireUserVerification,
+ bytes32 _x,
+ bytes32 _y,
+ bytes32 _metadata
+ )
+ {
+ unchecked {
+ // Global flag encoding:
+ // 0000 000X : requireUserVerification
+ // 0000 00X0 : 1 if 16 bits for authenticatorData size, 0 if 8 bits
+ // 0000 0X00 : 1 if 16 bits for clientDataJSON size, 0 if 8 bits
+ // 0000 X000 : 1 if 16 bits for challengeIndex, 0 if 8 bits
+ // 000X 0000 : 1 if 16 bits for typeIndex, 0 if 8 bits
+ // 00X0 0000 : 1 if fallback to abi decode data
+ // 0X00 0000 : 1 if signature has metadata node
+ // X000 0000 : unused
+
+ bytes1 flags = _signature[0];
+ if ((flags & 0x20) == 0) {
+ _requireUserVerification = (flags & 0x01) != 0;
+ uint256 bytesAuthDataSize = ((uint8(flags & 0x02)) >> 1) + 1;
+ uint256 bytesClientDataJSONSize = ((uint8(flags & 0x04)) >> 2) + 1;
+ uint256 bytesChallengeIndex = ((uint8(flags & 0x08)) >> 3) + 1;
+ uint256 bytesTypeIndex = ((uint8(flags & 0x10)) >> 4) + 1;
+
+ uint256 pointer = 1;
+
+ if ((flags & 0x40) != 0) {
+ (_metadata, pointer) = LibBytes.readBytes32(_signature, pointer);
+ }
+
+ {
+ uint256 authDataSize;
+ (authDataSize, pointer) = LibBytes.readUintX(_signature, pointer, bytesAuthDataSize);
+ uint256 nextPointer = pointer + authDataSize;
+ _webAuthnAuth.authenticatorData = _signature[pointer:nextPointer];
+ pointer = nextPointer;
+ }
+
+ {
+ uint256 clientDataJSONSize;
+ (clientDataJSONSize, pointer) = LibBytes.readUintX(_signature, pointer, bytesClientDataJSONSize);
+ uint256 nextPointer = pointer + clientDataJSONSize;
+ _webAuthnAuth.clientDataJSON = string(_signature[pointer:nextPointer]);
+ pointer = nextPointer;
+ }
+
+ (_webAuthnAuth.challengeIndex, pointer) = LibBytes.readUintX(_signature, pointer, bytesChallengeIndex);
+ (_webAuthnAuth.typeIndex, pointer) = LibBytes.readUintX(_signature, pointer, bytesTypeIndex);
+
+ (_webAuthnAuth.r, pointer) = LibBytes.readBytes32(_signature, pointer);
+ (_webAuthnAuth.s, pointer) = LibBytes.readBytes32(_signature, pointer);
+
+ (_x, pointer) = LibBytes.readBytes32(_signature, pointer);
+ (_y, pointer) = LibBytes.readBytes32(_signature, pointer);
+ } else {
+ (_webAuthnAuth, _requireUserVerification, _x, _y, _metadata) =
+ abi.decode(_signature[1:], (WebAuthn.WebAuthnAuth, bool, bytes32, bytes32, bytes32));
+ }
+ }
+ }
+
+ /// @inheritdoc ISapientCompact
+ function recoverSapientSignatureCompact(bytes32 _digest, bytes calldata _signature) external view returns (bytes32) {
+ (
+ WebAuthn.WebAuthnAuth memory _webAuthnAuth,
+ bool _requireUserVerification,
+ bytes32 _x,
+ bytes32 _y,
+ bytes32 _metadata
+ ) = _decodeSignature(_signature);
+
+ if (!WebAuthn.verify(abi.encodePacked(_digest), _requireUserVerification, _webAuthnAuth, _x, _y)) {
+ revert InvalidPasskeySignature(_webAuthnAuth, _requireUserVerification, _x, _y);
+ }
+
+ return _rootForPasskey(_requireUserVerification, _x, _y, _metadata);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/recovery/Recovery.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/recovery/Recovery.sol
new file mode 100644
index 000000000..76a461d20
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/recovery/Recovery.sol
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../modules/Payload.sol";
+import { IERC1271, IERC1271_MAGIC_VALUE_HASH } from "../../modules/interfaces/IERC1271.sol";
+import { ISapientCompact } from "../../modules/interfaces/ISapient.sol";
+import { LibBytes } from "../../utils/LibBytes.sol";
+import { LibOptim } from "../../utils/LibOptim.sol";
+
+using LibBytes for bytes;
+
+/// @title Recovery
+/// @author Agustin Aguilar, William Hua, Michael Standen
+/// @notice A recovery mode sapient signer
+contract Recovery is ISapientCompact {
+
+ bytes32 private constant EIP712_DOMAIN_TYPEHASH =
+ keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
+
+ bytes32 private constant EIP712_DOMAIN_NAME_SEQUENCE = keccak256("Sequence Wallet - Recovery Mode");
+ bytes32 private constant EIP712_DOMAIN_VERSION_SEQUENCE = keccak256("1");
+
+ // Make them similar to the flags in BaseSig.sol
+ uint256 internal constant FLAG_RECOVERY_LEAF = 1;
+ uint256 internal constant FLAG_NODE = 3;
+ uint256 internal constant FLAG_BRANCH = 4;
+
+ /// @notice Emitted when a new payload is queued
+ event NewQueuedPayload(address _wallet, address _signer, bytes32 _payloadHash, uint256 _timestamp);
+
+ /// @notice Error thrown when the signature is invalid
+ error InvalidSignature(address _wallet, address _signer, Payload.Decoded _payload, bytes _signature);
+ /// @notice Error thrown when the payload is already queued
+ error AlreadyQueued(address _wallet, address _signer, bytes32 _payloadHash);
+ /// @notice Error thrown when the queue is not ready
+ error QueueNotReady(address _wallet, bytes32 _payloadHash);
+ /// @notice Error thrown when the signature flag is invalid
+ error InvalidSignatureFlag(uint256 _flag);
+
+ function domainSeparator(bool _noChainId, address _wallet) internal view returns (bytes32 _domainSeparator) {
+ return keccak256(
+ abi.encode(
+ EIP712_DOMAIN_TYPEHASH,
+ EIP712_DOMAIN_NAME_SEQUENCE,
+ EIP712_DOMAIN_VERSION_SEQUENCE,
+ _noChainId ? uint256(0) : uint256(block.chainid),
+ _wallet
+ )
+ );
+ }
+
+ /// @notice Mapping of queued timestamps
+ /// @dev wallet -> signer -> payloadHash -> timestamp
+ mapping(address => mapping(address => mapping(bytes32 => uint256))) public timestampForQueuedPayload;
+
+ /// @notice Mapping of queued payload hashes
+ /// @dev wallet -> signer -> payloadHash[]
+ mapping(address => mapping(address => bytes32[])) public queuedPayloadHashes;
+
+ /// @notice Get the total number of queued payloads
+ /// @param _wallet The wallet to get the total number of queued payloads for
+ /// @param _signer The signer to get the total number of queued payloads for
+ /// @return The total number of queued payloads
+ function totalQueuedPayloads(address _wallet, address _signer) public view returns (uint256) {
+ return queuedPayloadHashes[_wallet][_signer].length;
+ }
+
+ function _leafForRecoveryLeaf(
+ address _signer,
+ uint256 _requiredDeltaTime,
+ uint256 _minTimestamp
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked("Sequence recovery leaf:\n", _signer, _requiredDeltaTime, _minTimestamp));
+ }
+
+ function _recoverBranch(
+ address _wallet,
+ bytes32 _payloadHash,
+ bytes calldata _signature
+ ) internal view returns (bool verified, bytes32 root) {
+ uint256 rindex;
+
+ while (rindex < _signature.length) {
+ // The first byte is the flag, it determines if we are reading
+ uint256 flag;
+ (flag, rindex) = _signature.readUint8(rindex);
+
+ if (flag == FLAG_RECOVERY_LEAF) {
+ // Read the signer and requiredDeltaTime
+ address signer;
+ uint256 requiredDeltaTime;
+ uint256 minTimestamp;
+
+ (signer, rindex) = _signature.readAddress(rindex);
+ (requiredDeltaTime, rindex) = _signature.readUint24(rindex);
+ (minTimestamp, rindex) = _signature.readUint64(rindex);
+
+ // Check if we have a queued payload for this signer
+ uint256 queuedAt = timestampForQueuedPayload[_wallet][signer][_payloadHash];
+ if (queuedAt != 0 && queuedAt >= minTimestamp && block.timestamp - queuedAt >= requiredDeltaTime) {
+ verified = true;
+ }
+
+ bytes32 node = _leafForRecoveryLeaf(signer, requiredDeltaTime, minTimestamp);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ if (flag == FLAG_NODE) {
+ // Read node hash
+ bytes32 node;
+ (node, rindex) = _signature.readBytes32(rindex);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ if (flag == FLAG_BRANCH) {
+ // Read size
+ uint256 size;
+ (size, rindex) = _signature.readUint24(rindex);
+
+ // Enter a branch of the signature merkle tree
+ uint256 nrindex = rindex + size;
+
+ (bool nverified, bytes32 nroot) = _recoverBranch(_wallet, _payloadHash, _signature[rindex:nrindex]);
+ rindex = nrindex;
+
+ verified = verified || nverified;
+ root = LibOptim.fkeccak256(root, nroot);
+ continue;
+ }
+
+ revert InvalidSignatureFlag(flag);
+ }
+
+ return (verified, root);
+ }
+
+ /// @notice Get the recovery payload hash
+ /// @param _wallet The wallet to get the recovery payload hash for
+ /// @param _payload The payload to get the recovery payload hash for
+ /// @return The recovery payload hash
+ function recoveryPayloadHash(address _wallet, Payload.Decoded calldata _payload) public view returns (bytes32) {
+ bytes32 domain = domainSeparator(_payload.noChainId, _wallet);
+ bytes32 structHash = Payload.toEIP712(_payload);
+ return keccak256(abi.encodePacked("\x19\x01", domain, structHash));
+ }
+
+ /// @inheritdoc ISapientCompact
+ function recoverSapientSignatureCompact(
+ bytes32 _payloadHash,
+ bytes calldata _signature
+ ) external view returns (bytes32) {
+ (bool verified, bytes32 root) = _recoverBranch(msg.sender, _payloadHash, _signature);
+ if (!verified) {
+ revert QueueNotReady(msg.sender, _payloadHash);
+ }
+
+ return root;
+ }
+
+ /// @notice Queue a payload for recovery
+ /// @param _wallet The wallet to queue the payload for
+ /// @param _signer The signer to queue the payload for
+ /// @param _payload The payload to queue
+ /// @param _signature The signature to queue the payload for
+ function queuePayload(
+ address _wallet,
+ address _signer,
+ Payload.Decoded calldata _payload,
+ bytes calldata _signature
+ ) external {
+ if (!isValidSignature(_wallet, _signer, _payload, _signature)) {
+ revert InvalidSignature(_wallet, _signer, _payload, _signature);
+ }
+
+ bytes32 payloadHash = Payload.hashFor(_payload, _wallet);
+ if (timestampForQueuedPayload[_wallet][_signer][payloadHash] != 0) {
+ revert AlreadyQueued(_wallet, _signer, payloadHash);
+ }
+
+ timestampForQueuedPayload[_wallet][_signer][payloadHash] = block.timestamp;
+ queuedPayloadHashes[_wallet][_signer].push(payloadHash);
+
+ emit NewQueuedPayload(_wallet, _signer, payloadHash, block.timestamp);
+ }
+
+ function isValidSignature(
+ address _wallet,
+ address _signer,
+ Payload.Decoded calldata _payload,
+ bytes calldata _signature
+ ) internal view returns (bool) {
+ bytes32 rPayloadHash = recoveryPayloadHash(_wallet, _payload);
+
+ if (_signature.length == 64) {
+ // Try an ECDSA signature
+ bytes32 r;
+ bytes32 s;
+ uint8 v;
+ (r, s, v,) = _signature.readRSVCompact(0);
+
+ address addr = ecrecover(rPayloadHash, v, r, s);
+ if (addr == _signer) {
+ return true;
+ }
+ }
+
+ if (_signer.code.length != 0) {
+ // ERC1271
+ return IERC1271(_signer).isValidSignature(rPayloadHash, _signature) == IERC1271_MAGIC_VALUE_HASH;
+ }
+
+ return false;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionErrors.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionErrors.sol
new file mode 100644
index 000000000..8db69d3e8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionErrors.sol
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+/// @title SessionErrors
+/// @author Michael Standen
+/// @notice Errors for the session manager
+library SessionErrors {
+
+ /// @notice Invalid session signer
+ error InvalidSessionSigner(address invalidSigner);
+ /// @notice Invalid chainId
+ error InvalidChainId(uint256 invalidChainId);
+ /// @notice Invalid self call
+ error InvalidSelfCall();
+ /// @notice Invalid delegate call
+ error InvalidDelegateCall();
+ /// @notice Invalid call behavior
+ error InvalidBehavior();
+ /// @notice Invalid value
+ error InvalidValue();
+ /// @notice Invalid node type in session configuration
+ error InvalidNodeType(uint256 flag);
+ /// @notice Error thrown when the payload kind is invalid
+ error InvalidPayloadKind();
+ /// @notice Error thrown when the calls length is invalid
+ error InvalidCallsLength();
+ /// @notice Error thrown when the payload space is invalid
+ error InvalidSpace(uint256 space);
+
+ // ---- Explicit session errors ----
+
+ /// @notice Missing permission for explicit session
+ error MissingPermission();
+ /// @notice Invalid permission for explicit session
+ error InvalidPermission();
+ /// @notice Session expired
+ error SessionExpired(uint256 deadline);
+ /// @notice Invalid limit usage increment
+ error InvalidLimitUsageIncrement();
+
+ // ---- Implicit session errors ----
+
+ /// @notice Blacklisted address
+ error BlacklistedAddress(address target);
+ /// @notice Invalid implicit result
+ error InvalidImplicitResult();
+ /// @notice Invalid identity signer
+ error InvalidIdentitySigner();
+ /// @notice Invalid blacklist
+ error InvalidBlacklist();
+ /// @notice Invalid attestation
+ error InvalidAttestation();
+ /// @notice The blacklist was not sorted
+ error InvalidBlacklistUnsorted();
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionManager.sol
new file mode 100644
index 000000000..dee209413
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionManager.sol
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../modules/Payload.sol";
+import { ISapient } from "../../modules/interfaces/ISapient.sol";
+import { LibBytes } from "../../utils/LibBytes.sol";
+
+import { SessionErrors } from "./SessionErrors.sol";
+import { SessionSig } from "./SessionSig.sol";
+import {
+ ExplicitSessionManager,
+ IExplicitSessionManager,
+ SessionPermissions,
+ SessionUsageLimits
+} from "./explicit/ExplicitSessionManager.sol";
+import { Permission, UsageLimit } from "./explicit/Permission.sol";
+import { ImplicitSessionManager } from "./implicit/ImplicitSessionManager.sol";
+
+using LibBytes for bytes;
+
+/// @title SessionManager
+/// @author Michael Standen, Agustin Aguilar
+/// @notice Manager for smart sessions
+contract SessionManager is ISapient, ImplicitSessionManager, ExplicitSessionManager {
+
+ /// @notice Maximum nonce space allowed for sessions use.
+ /// @dev This excludes half the possible bits (uint160 vs uint80)
+ uint256 public constant MAX_SPACE = type(uint80).max - 1;
+
+ /// @inheritdoc ISapient
+ function recoverSapientSignature(
+ Payload.Decoded calldata payload,
+ bytes calldata encodedSignature
+ ) external view returns (bytes32) {
+ // Validate outer Payload
+ if (payload.kind != Payload.KIND_TRANSACTIONS) {
+ revert SessionErrors.InvalidPayloadKind();
+ }
+ if (payload.space > MAX_SPACE) {
+ revert SessionErrors.InvalidSpace(payload.space);
+ }
+ if (payload.calls.length == 0) {
+ revert SessionErrors.InvalidCallsLength();
+ }
+
+ // Decode signature
+ SessionSig.DecodedSignature memory sig = SessionSig.recoverSignature(payload, encodedSignature);
+
+ address wallet = msg.sender;
+
+ // Initialize session usage limits for explicit session
+ SessionUsageLimits[] memory sessionUsageLimits = new SessionUsageLimits[](payload.calls.length);
+
+ for (uint256 i = 0; i < payload.calls.length; i++) {
+ Payload.Call calldata call = payload.calls[i];
+
+ // Ban delegate calls
+ if (call.delegateCall) {
+ revert SessionErrors.InvalidDelegateCall();
+ }
+ // Ban self calls to the wallet
+ if (call.to == wallet) {
+ revert SessionErrors.InvalidSelfCall();
+ }
+
+ // Check if this call could cause usage limits to be skipped
+ if (call.behaviorOnError == Payload.BEHAVIOR_ABORT_ON_ERROR) {
+ revert SessionErrors.InvalidBehavior();
+ }
+
+ // Validate call signature
+ SessionSig.CallSignature memory callSignature = sig.callSignatures[i];
+ if (callSignature.isImplicit) {
+ // Validate implicit calls
+ _validateImplicitCall(
+ call, wallet, callSignature.sessionSigner, callSignature.attestation, sig.implicitBlacklist
+ );
+ } else {
+ // Find the session usage limits for the current call
+ SessionUsageLimits memory limits;
+ uint256 limitsIdx;
+ for (limitsIdx = 0; limitsIdx < sessionUsageLimits.length; limitsIdx++) {
+ if (sessionUsageLimits[limitsIdx].signer == address(0)) {
+ // Initialize new session usage limits
+ limits.signer = callSignature.sessionSigner;
+ limits.limits = new UsageLimit[](0);
+ bytes32 usageHash = keccak256(abi.encode(callSignature.sessionSigner, VALUE_TRACKING_ADDRESS));
+ limits.totalValueUsed = getLimitUsage(wallet, usageHash);
+ break;
+ }
+ if (sessionUsageLimits[limitsIdx].signer == callSignature.sessionSigner) {
+ limits = sessionUsageLimits[limitsIdx];
+ break;
+ }
+ }
+ // Validate explicit calls. Obtain usage limits for increment validation.
+ (limits) = _validateExplicitCall(
+ payload,
+ i,
+ wallet,
+ callSignature.sessionSigner,
+ sig.sessionPermissions,
+ callSignature.sessionPermission,
+ limits
+ );
+ sessionUsageLimits[limitsIdx] = limits;
+ }
+ }
+
+ {
+ // Reduce the size of the sessionUsageLimits array
+ SessionUsageLimits[] memory actualSessionUsageLimits = new SessionUsageLimits[](sessionUsageLimits.length);
+ uint256 actualSize;
+ for (uint256 i = 0; i < sessionUsageLimits.length; i++) {
+ if (sessionUsageLimits[i].limits.length > 0 || sessionUsageLimits[i].totalValueUsed > 0) {
+ actualSessionUsageLimits[actualSize] = sessionUsageLimits[i];
+ actualSize++;
+ }
+ }
+ assembly {
+ mstore(actualSessionUsageLimits, actualSize)
+ }
+
+ // Bulk validate the updated usage limits
+ Payload.Call calldata firstCall = payload.calls[0];
+ _validateLimitUsageIncrement(firstCall, actualSessionUsageLimits);
+ }
+
+ // Return the image hash
+ return sig.imageHash;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionSig.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionSig.sol
new file mode 100644
index 000000000..493b522fb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/SessionSig.sol
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../modules/Payload.sol";
+import { LibBytes } from "../../utils/LibBytes.sol";
+import { LibOptim } from "../../utils/LibOptim.sol";
+import { SessionErrors } from "./SessionErrors.sol";
+import { SessionPermissions } from "./explicit/IExplicitSessionManager.sol";
+import { LibPermission, Permission } from "./explicit/Permission.sol";
+import { Attestation, LibAttestation } from "./implicit/Attestation.sol";
+
+using LibBytes for bytes;
+using LibAttestation for Attestation;
+
+/// @title SessionSig
+/// @author Michael Standen, Agustin Aguilar
+/// @notice Library for session signatures
+library SessionSig {
+
+ uint256 internal constant FLAG_PERMISSIONS = 0;
+ uint256 internal constant FLAG_NODE = 1;
+ uint256 internal constant FLAG_BRANCH = 2;
+ uint256 internal constant FLAG_BLACKLIST = 3;
+ uint256 internal constant FLAG_IDENTITY_SIGNER = 4;
+
+ uint256 internal constant MIN_ENCODED_PERMISSION_SIZE = 94;
+
+ /// @notice Call signature for a specific session
+ /// @param isImplicit If the call is implicit
+ /// @param sessionSigner Address of the session signer
+ /// @param sessionPermission Session permission for explicit calls
+ /// @param attestation Attestation for implicit calls
+ struct CallSignature {
+ bool isImplicit;
+ address sessionSigner;
+ uint8 sessionPermission;
+ Attestation attestation;
+ }
+
+ /// @notice Decoded signature for a specific session
+ /// @param imageHash Derived configuration image hash
+ /// @param identitySigner Identity signer address
+ /// @param implicitBlacklist Implicit blacklist addresses
+ /// @param sessionPermissions Session permissions for each explicit signer
+ /// @param callSignatures Call signatures for each call in the payload
+ struct DecodedSignature {
+ bytes32 imageHash;
+ address identitySigner;
+ address[] implicitBlacklist;
+ SessionPermissions[] sessionPermissions;
+ CallSignature[] callSignatures;
+ }
+
+ /// @notice Recovers the decoded signature from the encodedSignature bytes.
+ /// @dev The encoded layout is conceptually separated into three parts:
+ /// 1) Session Configuration
+ /// 2) A reusable list of Attestations + their identity signatures (if any implicit calls exist)
+ /// 3) Call Signatures (one per call in the payload)
+ ///
+ /// High-level layout:
+ /// - session_configuration: [uint24 size, ]
+ /// - attestation_list: [uint8 attestationCount, (Attestation + identitySig) * attestationCount]
+ /// (new section to allow reusing the same Attestation across multiple calls)
+ /// - call_signatures: [] - Size is payload.calls.length
+ /// - call_signature: [uint8 call_flags, ]
+ /// - call_flags: [bool is_implicit (MSB), 7 bits encoded]
+ /// - if call_flags.is_implicit.MSB == 1:
+ /// - attestation_index: [uint8 index into the attestation list (7 bits of the call_flags)]
+ /// - session_signature: [r, s, v (compact)]
+ /// - if call_flags.is_implicit.MSB == 0:
+ /// - session_permission: [uint8 (7 bits of the call_flags)]
+ /// - session_signature: [r, s, v (compact)]
+ function recoverSignature(
+ Payload.Decoded calldata payload,
+ bytes calldata encodedSignature
+ ) internal view returns (DecodedSignature memory sig) {
+ uint256 pointer = 0;
+ bool hasBlacklistInConfig;
+
+ // ----- Session Configuration -----
+ {
+ // First read the length of the session configuration bytes (uint24)
+ uint256 dataSize;
+ (dataSize, pointer) = encodedSignature.readUint24(pointer);
+
+ // Recover the session configuration
+ (sig, hasBlacklistInConfig) = recoverConfiguration(encodedSignature[pointer:pointer + dataSize]);
+ pointer += dataSize;
+
+ // Identity signer must be set
+ if (sig.identitySigner == address(0)) {
+ revert SessionErrors.InvalidIdentitySigner();
+ }
+ }
+
+ // ----- Attestations for implicit calls -----
+ Attestation[] memory attestationList;
+ {
+ uint8 attestationCount;
+ (attestationCount, pointer) = encodedSignature.readUint8(pointer);
+ attestationList = new Attestation[](attestationCount);
+ // Parse each attestation and its identity signature, store in memory
+ for (uint256 i = 0; i < attestationCount; i++) {
+ Attestation memory att;
+ (att, pointer) = LibAttestation.fromPacked(encodedSignature, pointer);
+
+ // Read the identity signature that approves this attestation
+ {
+ bytes32 r;
+ bytes32 s;
+ uint8 v;
+ (r, s, v, pointer) = encodedSignature.readRSVCompact(pointer);
+
+ // Recover the identity signer from the attestation identity signature
+ bytes32 attestationHash = att.toHash();
+ address recoveredIdentitySigner = ecrecover(attestationHash, v, r, s);
+ if (recoveredIdentitySigner != sig.identitySigner) {
+ revert SessionErrors.InvalidIdentitySigner();
+ }
+ }
+
+ attestationList[i] = att;
+ }
+
+ // If we have any implicit calls, we must have a blacklist in the configuration
+ if (attestationCount > 0 && !hasBlacklistInConfig) {
+ revert SessionErrors.InvalidBlacklist();
+ }
+ }
+
+ // ----- Call Signatures -----
+ {
+ uint256 callsCount = payload.calls.length;
+ sig.callSignatures = new CallSignature[](callsCount);
+
+ for (uint256 i = 0; i < callsCount; i++) {
+ CallSignature memory callSignature;
+
+ // Determine signature type
+ {
+ uint8 flag;
+ (flag, pointer) = encodedSignature.readUint8(pointer);
+ callSignature.isImplicit = (flag & 0x80) != 0;
+
+ if (callSignature.isImplicit) {
+ // Read attestation index from the call_flags
+ uint8 attestationIndex = uint8(flag & 0x7f);
+
+ // Check if the attestation index is out of range
+ if (attestationIndex >= attestationList.length) {
+ revert SessionErrors.InvalidAttestation();
+ }
+
+ // Set the attestation
+ callSignature.attestation = attestationList[attestationIndex];
+ } else {
+ // Session permission index is the entire byte, top bit is 0 => no conflict
+ callSignature.sessionPermission = flag;
+ }
+ }
+
+ // Read session signature and recover the signer
+ {
+ bytes32 r;
+ bytes32 s;
+ uint8 v;
+ (r, s, v, pointer) = encodedSignature.readRSVCompact(pointer);
+
+ bytes32 callHash = hashCallWithReplayProtection(payload, i);
+ callSignature.sessionSigner = ecrecover(callHash, v, r, s);
+ if (callSignature.sessionSigner == address(0)) {
+ revert SessionErrors.InvalidSessionSigner(address(0));
+ }
+ }
+
+ sig.callSignatures[i] = callSignature;
+ }
+ }
+
+ return sig;
+ }
+
+ /// @notice Recovers the session configuration from the encoded data.
+ /// The encoded layout is:
+ /// - permissions_count: [uint8]
+ /// - permissions_tree_element: [flag, ]
+ /// - flag: [uint8]
+ /// - data: [data]
+ /// - if flag == FLAG_PERMISSIONS: [SessionPermissions encoded]
+ /// - if flag == FLAG_NODE: [bytes32 node]
+ /// - if flag == FLAG_BRANCH: [uint256 size, nested encoding...]
+ /// - if flag == FLAG_BLACKLIST: [uint24 blacklist_count, blacklist_addresses...]
+ /// - if flag == FLAG_IDENTITY_SIGNER: [address identity_signer]
+ /// @dev A valid configuration must have exactly one identity signer and at most one blacklist.
+ function recoverConfiguration(
+ bytes calldata encoded
+ ) internal pure returns (DecodedSignature memory sig, bool hasBlacklist) {
+ uint256 pointer;
+ uint256 permissionsCount;
+
+ // Guess maximum permissions size by bytes length
+ {
+ uint256 maxPermissionsSize = encoded.length / MIN_ENCODED_PERMISSION_SIZE;
+ sig.sessionPermissions = new SessionPermissions[](maxPermissionsSize);
+ }
+
+ while (pointer < encoded.length) {
+ // First byte is the flag (top 4 bits) and additional data (bottom 4 bits)
+ uint256 firstByte;
+ (firstByte, pointer) = encoded.readUint8(pointer);
+ // The top 4 bits are the flag
+ uint256 flag = (firstByte & 0xf0) >> 4;
+
+ // Permissions configuration (0x00)
+ if (flag == FLAG_PERMISSIONS) {
+ SessionPermissions memory nodePermissions;
+ uint256 pointerStart = pointer;
+
+ // Read signer
+ (nodePermissions.signer, pointer) = encoded.readAddress(pointer);
+
+ // Read chainId
+ (nodePermissions.chainId, pointer) = encoded.readUint256(pointer);
+
+ // Read value limit
+ (nodePermissions.valueLimit, pointer) = encoded.readUint256(pointer);
+
+ // Read deadline
+ (nodePermissions.deadline, pointer) = encoded.readUint64(pointer);
+
+ // Read permissions array
+ (nodePermissions.permissions, pointer) = _decodePermissions(encoded, pointer);
+
+ // Update root
+ {
+ bytes32 permissionHash = _leafHashForPermissions(encoded[pointerStart:pointer]);
+ sig.imageHash =
+ sig.imageHash != bytes32(0) ? LibOptim.fkeccak256(sig.imageHash, permissionHash) : permissionHash;
+ }
+
+ // Push node permissions to the permissions array
+ sig.sessionPermissions[permissionsCount++] = nodePermissions;
+ continue;
+ }
+
+ // Node (0x01)
+ if (flag == FLAG_NODE) {
+ // Read pre-hashed node
+ bytes32 node;
+ (node, pointer) = encoded.readBytes32(pointer);
+
+ // Update root
+ sig.imageHash = sig.imageHash != bytes32(0) ? LibOptim.fkeccak256(sig.imageHash, node) : node;
+
+ continue;
+ }
+
+ // Branch (0x02)
+ if (flag == FLAG_BRANCH) {
+ // Read branch size
+ uint256 size;
+ {
+ uint256 sizeSize = uint8(firstByte & 0x0f);
+ (size, pointer) = encoded.readUintX(pointer, sizeSize);
+ }
+ // Process branch
+ uint256 nrindex = pointer + size;
+ (DecodedSignature memory branchSig, bool branchHasBlacklist) = recoverConfiguration(encoded[pointer:nrindex]);
+ pointer = nrindex;
+
+ // Store the branch blacklist
+ if (branchHasBlacklist) {
+ if (hasBlacklist) {
+ // Blacklist already set
+ revert SessionErrors.InvalidBlacklist();
+ }
+ hasBlacklist = true;
+ sig.implicitBlacklist = branchSig.implicitBlacklist;
+ }
+
+ // Store the branch identity signer
+ if (branchSig.identitySigner != address(0)) {
+ if (sig.identitySigner != address(0)) {
+ // Identity signer already set
+ revert SessionErrors.InvalidIdentitySigner();
+ }
+ sig.identitySigner = branchSig.identitySigner;
+ }
+
+ // Push all branch permissions to the permissions array
+ for (uint256 i = 0; i < branchSig.sessionPermissions.length; i++) {
+ sig.sessionPermissions[permissionsCount++] = branchSig.sessionPermissions[i];
+ }
+
+ // Update root
+ sig.imageHash =
+ sig.imageHash != bytes32(0) ? LibOptim.fkeccak256(sig.imageHash, branchSig.imageHash) : branchSig.imageHash;
+
+ continue;
+ }
+
+ // Blacklist (0x03)
+ if (flag == FLAG_BLACKLIST) {
+ if (hasBlacklist) {
+ // Blacklist already set
+ revert SessionErrors.InvalidBlacklist();
+ }
+ hasBlacklist = true;
+
+ // Read the blacklist count from the first byte's lower 4 bits
+ uint256 blacklistCount = uint256(firstByte & 0x0f);
+ if (blacklistCount == 0x0f) {
+ // If it's max nibble, read the next 2 bytes for the actual size
+ (blacklistCount, pointer) = encoded.readUint16(pointer);
+ }
+ uint256 pointerStart = pointer;
+
+ // Read the blacklist addresses
+ sig.implicitBlacklist = new address[](blacklistCount);
+ address previousAddress;
+ for (uint256 i = 0; i < blacklistCount; i++) {
+ (sig.implicitBlacklist[i], pointer) = encoded.readAddress(pointer);
+ if (sig.implicitBlacklist[i] < previousAddress) {
+ revert SessionErrors.InvalidBlacklistUnsorted();
+ }
+ previousAddress = sig.implicitBlacklist[i];
+ }
+
+ // Update the root
+ bytes32 blacklistHash = _leafHashForBlacklist(encoded[pointerStart:pointer]);
+ sig.imageHash = sig.imageHash != bytes32(0) ? LibOptim.fkeccak256(sig.imageHash, blacklistHash) : blacklistHash;
+
+ continue;
+ }
+
+ // Identity signer (0x04)
+ if (flag == FLAG_IDENTITY_SIGNER) {
+ if (sig.identitySigner != address(0)) {
+ // Identity signer already set
+ revert SessionErrors.InvalidIdentitySigner();
+ }
+ (sig.identitySigner, pointer) = encoded.readAddress(pointer);
+
+ // Update the root
+ bytes32 identitySignerHash = _leafHashForIdentitySigner(sig.identitySigner);
+ sig.imageHash =
+ sig.imageHash != bytes32(0) ? LibOptim.fkeccak256(sig.imageHash, identitySignerHash) : identitySignerHash;
+
+ continue;
+ }
+
+ revert SessionErrors.InvalidNodeType(flag);
+ }
+
+ {
+ // Update the permissions array length to the actual count
+ SessionPermissions[] memory permissions = sig.sessionPermissions;
+ assembly {
+ mstore(permissions, permissionsCount)
+ }
+ }
+
+ return (sig, hasBlacklist);
+ }
+
+ /// @notice Decodes an array of Permission objects from the encoded data.
+ function _decodePermissions(
+ bytes calldata encoded,
+ uint256 pointer
+ ) internal pure returns (Permission[] memory permissions, uint256 newPointer) {
+ uint256 length;
+ (length, pointer) = encoded.readUint8(pointer);
+ permissions = new Permission[](length);
+ for (uint256 i = 0; i < length; i++) {
+ (permissions[i], pointer) = LibPermission.readPermission(encoded, pointer);
+ }
+ return (permissions, pointer);
+ }
+
+ /// @notice Hashes the encoded session permissions into a leaf node.
+ function _leafHashForPermissions(
+ bytes calldata encodedPermissions
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(uint8(FLAG_PERMISSIONS), encodedPermissions));
+ }
+
+ /// @notice Hashes the encoded blacklist into a leaf node.
+ function _leafHashForBlacklist(
+ bytes calldata encodedBlacklist
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(uint8(FLAG_BLACKLIST), encodedBlacklist));
+ }
+
+ /// @notice Hashes the identity signer into a leaf node.
+ function _leafHashForIdentitySigner(
+ address identitySigner
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(uint8(FLAG_IDENTITY_SIGNER), identitySigner));
+ }
+
+ /// @notice Hashes a call with replay protection.
+ /// @dev The replay protection is based on the chainId, space, nonce and index in the payload.
+ /// @param payload The payload to hash
+ /// @param callIdx The index of the call to hash
+ /// @return callHash The hash of the call with replay protection
+ function hashCallWithReplayProtection(
+ Payload.Decoded calldata payload,
+ uint256 callIdx
+ ) public view returns (bytes32 callHash) {
+ return keccak256(
+ abi.encodePacked(
+ payload.noChainId ? 0 : block.chainid,
+ payload.space,
+ payload.nonce,
+ callIdx,
+ Payload.hashCall(payload.calls[callIdx])
+ )
+ );
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/ExplicitSessionManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/ExplicitSessionManager.sol
new file mode 100644
index 000000000..042ce1afb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/ExplicitSessionManager.sol
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../../modules/Payload.sol";
+import { LibBytes } from "../../../utils/LibBytes.sol";
+
+import { SessionErrors } from "../SessionErrors.sol";
+import { IExplicitSessionManager, SessionPermissions, SessionUsageLimits } from "./IExplicitSessionManager.sol";
+import { Permission, UsageLimit } from "./Permission.sol";
+import { PermissionValidator } from "./PermissionValidator.sol";
+
+abstract contract ExplicitSessionManager is IExplicitSessionManager, PermissionValidator {
+
+ using LibBytes for bytes;
+
+ /// @notice Special address used for tracking native token value limits
+ address public constant VALUE_TRACKING_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
+
+ /// @inheritdoc IExplicitSessionManager
+ function incrementUsageLimit(
+ UsageLimit[] calldata limits
+ ) external {
+ address wallet = msg.sender;
+ for (uint256 i = 0; i < limits.length; i++) {
+ if (limits[i].usageAmount < getLimitUsage(wallet, limits[i].usageHash)) {
+ // Cannot decrement usage limit
+ revert SessionErrors.InvalidLimitUsageIncrement();
+ }
+ setLimitUsage(wallet, limits[i].usageHash, limits[i].usageAmount);
+ }
+ }
+
+ /// @notice Validates an explicit call
+ /// @param payload The decoded payload containing calls
+ /// @param callIdx The index of the call to validate
+ /// @param wallet The wallet's address
+ /// @param sessionSigner The session signer's address
+ /// @param allSessionPermissions All sessions' permissions
+ /// @param permissionIdx The index of the permission to validate
+ /// @param sessionUsageLimits The session usage limits
+ /// @return newSessionUsageLimits The updated session usage limits
+ function _validateExplicitCall(
+ Payload.Decoded calldata payload,
+ uint256 callIdx,
+ address wallet,
+ address sessionSigner,
+ SessionPermissions[] memory allSessionPermissions,
+ uint8 permissionIdx,
+ SessionUsageLimits memory sessionUsageLimits
+ ) internal view returns (SessionUsageLimits memory newSessionUsageLimits) {
+ // Find the permissions for the given session signer
+ SessionPermissions memory sessionPermissions;
+ for (uint256 i = 0; i < allSessionPermissions.length; i++) {
+ if (allSessionPermissions[i].signer == sessionSigner) {
+ sessionPermissions = allSessionPermissions[i];
+ break;
+ }
+ }
+ if (sessionPermissions.signer == address(0)) {
+ revert SessionErrors.InvalidSessionSigner(sessionSigner);
+ }
+
+ // Check if session chainId is valid
+ if (sessionPermissions.chainId != 0 && sessionPermissions.chainId != block.chainid) {
+ revert SessionErrors.InvalidChainId(sessionPermissions.chainId);
+ }
+
+ // Check if session has expired.
+ if (sessionPermissions.deadline != 0 && block.timestamp > sessionPermissions.deadline) {
+ revert SessionErrors.SessionExpired(sessionPermissions.deadline);
+ }
+
+ // Delegate calls are not allowed
+ Payload.Call calldata call = payload.calls[callIdx];
+ if (call.delegateCall) {
+ revert SessionErrors.InvalidDelegateCall();
+ }
+
+ // Calls to incrementUsageLimit are the only allowed calls to this contract
+ if (call.to == address(this)) {
+ if (callIdx != 0) {
+ // IncrementUsageLimit call is only allowed as the first call
+ revert SessionErrors.InvalidLimitUsageIncrement();
+ }
+ if (call.value > 0) {
+ revert SessionErrors.InvalidValue();
+ }
+ // No permissions required for the increment call
+ return sessionUsageLimits;
+ }
+
+ // Get the permission for the current call
+ if (permissionIdx >= sessionPermissions.permissions.length) {
+ revert SessionErrors.MissingPermission();
+ }
+ Permission memory permission = sessionPermissions.permissions[permissionIdx];
+
+ // Validate the permission for the current call
+ (bool isValid, UsageLimit[] memory limits) =
+ validatePermission(permission, call, wallet, sessionSigner, sessionUsageLimits.limits);
+ if (!isValid) {
+ revert SessionErrors.InvalidPermission();
+ }
+ sessionUsageLimits.limits = limits;
+
+ // Increment the total value used
+ if (call.value > 0) {
+ sessionUsageLimits.totalValueUsed += call.value;
+ }
+ if (sessionUsageLimits.totalValueUsed > sessionPermissions.valueLimit) {
+ // Value limit exceeded
+ revert SessionErrors.InvalidValue();
+ }
+
+ return sessionUsageLimits;
+ }
+
+ /// @notice Verifies the limit usage increment
+ /// @param call The first call in the payload, which is expected to be the increment call
+ /// @param sessionUsageLimits The session usage limits
+ /// @dev Reverts if the required increment call is missing or invalid
+ /// @dev If no usage limits are used, this function does nothing
+ function _validateLimitUsageIncrement(
+ Payload.Call calldata call,
+ SessionUsageLimits[] memory sessionUsageLimits
+ ) internal view {
+ // Limits call is only required if there are usage limits used
+ if (sessionUsageLimits.length > 0) {
+ // Verify the first call is the increment call and cannot be skipped
+ if (call.to != address(this) || call.behaviorOnError != Payload.BEHAVIOR_REVERT_ON_ERROR || call.onlyFallback) {
+ revert SessionErrors.InvalidLimitUsageIncrement();
+ }
+
+ // Construct expected limit increments
+ uint256 totalLimitsLength = 0;
+ for (uint256 i = 0; i < sessionUsageLimits.length; i++) {
+ totalLimitsLength += sessionUsageLimits[i].limits.length;
+ if (sessionUsageLimits[i].totalValueUsed > 0) {
+ totalLimitsLength++;
+ }
+ }
+ UsageLimit[] memory limits = new UsageLimit[](totalLimitsLength);
+ uint256 limitIndex = 0;
+ for (uint256 i = 0; i < sessionUsageLimits.length; i++) {
+ for (uint256 j = 0; j < sessionUsageLimits[i].limits.length; j++) {
+ limits[limitIndex++] = sessionUsageLimits[i].limits[j];
+ }
+ if (sessionUsageLimits[i].totalValueUsed > 0) {
+ limits[limitIndex++] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionUsageLimits[i].signer, VALUE_TRACKING_ADDRESS)),
+ usageAmount: sessionUsageLimits[i].totalValueUsed
+ });
+ }
+ }
+
+ // Verify the increment call data
+ bytes memory expectedData = abi.encodeWithSelector(this.incrementUsageLimit.selector, limits);
+ bytes32 expectedDataHash = keccak256(expectedData);
+ bytes32 actualDataHash = keccak256(call.data);
+ if (actualDataHash != expectedDataHash) {
+ revert SessionErrors.InvalidLimitUsageIncrement();
+ }
+ } else {
+ // Do not allow self calls if there are no usage limits
+ if (call.to == address(this)) {
+ revert SessionErrors.InvalidLimitUsageIncrement();
+ }
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/IExplicitSessionManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/IExplicitSessionManager.sol
new file mode 100644
index 000000000..051391211
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/IExplicitSessionManager.sol
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Permission, UsageLimit } from "./Permission.sol";
+
+/// @notice Permissions configuration for a specific session signer
+/// @param signer Address of the session signer these permissions apply to
+/// @param chainId Chain ID of the session (0 = any chain)
+/// @param valueLimit Maximum native token value this signer can send
+/// @param deadline Deadline for the session. (0 = no deadline)
+/// @param permissions Array of encoded permissions granted to this signer
+struct SessionPermissions {
+ address signer;
+ uint256 chainId;
+ uint256 valueLimit;
+ uint64 deadline;
+ Permission[] permissions;
+}
+
+/// @notice Usage limits configuration for a specific session signer
+/// @param signer Address of the session signer these limits apply to
+/// @param limits Array of usage limits
+/// @param totalValueUsed Total native token value used
+struct SessionUsageLimits {
+ address signer;
+ UsageLimit[] limits;
+ uint256 totalValueUsed;
+}
+
+/// @title IExplicitSessionManager
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Interface for the explicit session manager
+interface IExplicitSessionManager {
+
+ /// @notice Increment usage for a caller's given session and target
+ /// @param limits Array of limit/session/target combinations
+ function incrementUsageLimit(
+ UsageLimit[] calldata limits
+ ) external;
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/Permission.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/Permission.sol
new file mode 100644
index 000000000..e9ec7452f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/Permission.sol
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { LibBytes } from "../../../utils/LibBytes.sol";
+
+/// @notice Permission for a specific session signer
+/// @param target Address of the target contract this permission applies to
+/// @param rules Array of parameter rules
+struct Permission {
+ address target;
+ ParameterRule[] rules;
+}
+
+/// @notice Parameter operation for a specific session signer
+enum ParameterOperation {
+ EQUAL,
+ NOT_EQUAL,
+ GREATER_THAN_OR_EQUAL,
+ LESS_THAN_OR_EQUAL
+}
+
+/// @notice Parameter rule for a specific session signer
+/// @param cumulative If the value should accumulate over multiple calls
+/// @param operation Operation to apply to the parameter
+/// @param value Value to compare against the masked parameter
+/// @param offset Offset in calldata to read the parameter
+/// @param mask Mask to apply to the parameter
+struct ParameterRule {
+ bool cumulative;
+ ParameterOperation operation;
+ bytes32 value;
+ uint256 offset;
+ bytes32 mask;
+}
+
+/// @notice Usage limit for a specific session signer
+/// @param usageHash Usage identifier
+/// @param usageAmount Amount of usage
+struct UsageLimit {
+ bytes32 usageHash;
+ uint256 usageAmount;
+}
+
+using LibBytes for bytes;
+
+/// @title LibPermission
+/// @author Michael Standen
+/// @notice Library for permission management
+library LibPermission {
+
+ /// @notice Error thrown when the rules length exceeds the maximum
+ error RulesLengthExceedsMax();
+
+ /// @notice Reads a permission from a packed bytes array
+ /// @param encoded The packed bytes array
+ /// @param pointer The pointer to the start of the permission
+ /// @return permission The decoded permission
+ /// @return newPointer The new pointer to the end of the permission
+ function readPermission(
+ bytes calldata encoded,
+ uint256 pointer
+ ) internal pure returns (Permission memory permission, uint256 newPointer) {
+ // Target
+ (permission.target, pointer) = encoded.readAddress(pointer);
+ // Rules
+ uint256 rulesLength;
+ (rulesLength, pointer) = encoded.readUint8(pointer);
+ permission.rules = new ParameterRule[](rulesLength);
+ for (uint256 i = 0; i < rulesLength; i++) {
+ uint8 operationCumulative;
+ (operationCumulative, pointer) = encoded.readUint8(pointer);
+ // 000X: cumulative
+ permission.rules[i].cumulative = operationCumulative & 1 != 0;
+ // XXX0: operation
+ permission.rules[i].operation = ParameterOperation(operationCumulative >> 1);
+
+ (permission.rules[i].value, pointer) = encoded.readBytes32(pointer);
+ (permission.rules[i].offset, pointer) = encoded.readUint256(pointer);
+ (permission.rules[i].mask, pointer) = encoded.readBytes32(pointer);
+ }
+ return (permission, pointer);
+ }
+
+ /// @notice Encodes a permission into a packed bytes array
+ /// @param permission The permission to encode
+ /// @return packed The packed bytes array
+ function toPacked(
+ Permission calldata permission
+ ) internal pure returns (bytes memory packed) {
+ if (permission.rules.length > type(uint8).max) {
+ revert RulesLengthExceedsMax();
+ }
+ packed = abi.encodePacked(permission.target, uint8(permission.rules.length));
+ for (uint256 i = 0; i < permission.rules.length; i++) {
+ packed = abi.encodePacked(packed, ruleToPacked(permission.rules[i]));
+ }
+ }
+
+ /// @notice Encodes a rule into a packed bytes array
+ /// @param rule The rule to encode
+ /// @return packed The packed bytes array
+ function ruleToPacked(
+ ParameterRule calldata rule
+ ) internal pure returns (bytes memory packed) {
+ // Combine operation and cumulative flag into a single byte
+ // 0x[operationx3][cumulative]
+ uint8 operationCumulative = (uint8(rule.operation) << 1) | (rule.cumulative ? 1 : 0);
+
+ return abi.encodePacked(operationCumulative, rule.value, rule.offset, rule.mask);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/PermissionValidator.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/PermissionValidator.sol
new file mode 100644
index 000000000..03bae46ef
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/explicit/PermissionValidator.sol
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../../modules/Payload.sol";
+import { LibBytes } from "../../../utils/LibBytes.sol";
+import { ParameterOperation, ParameterRule, Permission, UsageLimit } from "./Permission.sol";
+
+/// @title PermissionValidator
+/// @author Michael Standen, Agustin Aguilar
+/// @notice Validates permissions for a given call
+abstract contract PermissionValidator {
+
+ using LibBytes for bytes;
+
+ /// @notice Emitted when the usage amount for a given wallet and usage hash is updated
+ event LimitUsageUpdated(address wallet, bytes32 usageHash, uint256 usageAmount);
+
+ /// @notice Mapping of usage limit hashes to their usage amounts
+ mapping(address => mapping(bytes32 => uint256)) private limitUsage;
+
+ /// @notice Get the usage amount for a given usage hash and wallet
+ /// @param wallet The wallet address
+ /// @param usageHash The usage hash
+ /// @return The usage amount
+ function getLimitUsage(address wallet, bytes32 usageHash) public view returns (uint256) {
+ return limitUsage[wallet][usageHash];
+ }
+
+ /// @notice Set the usage amount for a given usage hash and wallet
+ /// @param wallet The wallet address
+ /// @param usageHash The usage hash
+ /// @param usageAmount The usage amount
+ function setLimitUsage(address wallet, bytes32 usageHash, uint256 usageAmount) internal {
+ limitUsage[wallet][usageHash] = usageAmount;
+ emit LimitUsageUpdated(wallet, usageHash, usageAmount);
+ }
+
+ /// @notice Validates a rules permission
+ /// @param permission The rules permission to validate
+ /// @param call The call to validate against
+ /// @param wallet The wallet address
+ /// @param signer The signer address
+ /// @param usageLimits Array of current usage limits
+ /// @return True if the permission is valid, false otherwise
+ /// @return newUsageLimits New array of usage limits
+ function validatePermission(
+ Permission memory permission,
+ Payload.Call calldata call,
+ address wallet,
+ address signer,
+ UsageLimit[] memory usageLimits
+ ) public view returns (bool, UsageLimit[] memory newUsageLimits) {
+ if (permission.target != call.to) {
+ return (false, usageLimits);
+ }
+
+ // Copy usage limits into array with space for new rules
+ newUsageLimits = new UsageLimit[](usageLimits.length + permission.rules.length);
+ for (uint256 i = 0; i < usageLimits.length; i++) {
+ newUsageLimits[i] = usageLimits[i];
+ }
+ uint256 actualLimitsCount = usageLimits.length;
+
+ // Check each rule
+ for (uint256 i = 0; i < permission.rules.length; i++) {
+ ParameterRule memory rule = permission.rules[i];
+
+ // Extract value from calldata at offset
+ (bytes32 value,) = call.data.readBytes32(rule.offset);
+
+ // Apply mask
+ value = value & rule.mask;
+
+ if (rule.cumulative) {
+ // Calculate cumulative usage
+ uint256 value256 = uint256(value);
+ // Find the usage limit for the current rule
+ bytes32 usageHash = keccak256(abi.encode(signer, permission, i));
+ uint256 previousUsage;
+ UsageLimit memory usageLimit;
+ for (uint256 j = 0; j < newUsageLimits.length; j++) {
+ if (newUsageLimits[j].usageHash == bytes32(0)) {
+ // Initialize new usage limit
+ usageLimit = UsageLimit({ usageHash: usageHash, usageAmount: 0 });
+ newUsageLimits[j] = usageLimit;
+ actualLimitsCount = j + 1;
+ break;
+ }
+ if (newUsageLimits[j].usageHash == usageHash) {
+ // Value exists, use it
+ usageLimit = newUsageLimits[j];
+ previousUsage = usageLimit.usageAmount;
+ break;
+ }
+ }
+ if (previousUsage == 0) {
+ // Not in current payload, use storage
+ previousUsage = getLimitUsage(wallet, usageHash);
+ }
+ // Cumulate usage
+ value256 += previousUsage;
+ usageLimit.usageAmount = value256;
+ // Use the cumulative value for comparison
+ value = bytes32(value256);
+ }
+
+ // Compare based on operation
+ if (rule.operation == ParameterOperation.EQUAL) {
+ if (value != rule.value) {
+ return (false, usageLimits);
+ }
+ } else if (rule.operation == ParameterOperation.LESS_THAN_OR_EQUAL) {
+ if (uint256(value) > uint256(rule.value)) {
+ return (false, usageLimits);
+ }
+ } else if (rule.operation == ParameterOperation.NOT_EQUAL) {
+ if (value == rule.value) {
+ return (false, usageLimits);
+ }
+ } else if (rule.operation == ParameterOperation.GREATER_THAN_OR_EQUAL) {
+ if (uint256(value) < uint256(rule.value)) {
+ return (false, usageLimits);
+ }
+ }
+ }
+
+ // Fix array length
+ assembly {
+ mstore(newUsageLimits, actualLimitsCount)
+ }
+
+ return (true, newUsageLimits);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/Attestation.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/Attestation.sol
new file mode 100644
index 000000000..657d9169c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/Attestation.sol
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { LibBytes } from "../../../utils/LibBytes.sol";
+import { ACCEPT_IMPLICIT_REQUEST_MAGIC_PREFIX } from "./ISignalsImplicitMode.sol";
+
+using LibBytes for bytes;
+
+/// @notice Attestation for a specific session
+/// @param approvedSigner Address of the approved signer
+/// @param identityType Identity type
+/// @param issuerHash Hash of the issuer
+/// @param audienceHash Hash of the audience
+/// @param applicationData Unspecified application data
+/// @param authData Auth data
+struct Attestation {
+ address approvedSigner;
+ bytes4 identityType;
+ bytes32 issuerHash;
+ bytes32 audienceHash;
+ bytes applicationData;
+ AuthData authData;
+}
+
+/// @notice Auth data for an attestation
+/// @param redirectUrl Authorization redirect URL
+/// @param issuedAt Timestamp of the attestation issuance
+struct AuthData {
+ string redirectUrl;
+ uint64 issuedAt;
+}
+
+/// @title LibAttestation
+/// @author Michael Standen
+/// @notice Library for attestation management
+library LibAttestation {
+
+ /// @notice Hashes an attestation
+ function toHash(
+ Attestation memory attestation
+ ) internal pure returns (bytes32) {
+ return keccak256(toPacked(attestation));
+ }
+
+ /// @notice Decodes an attestation from a packed bytes array
+ /// @param encoded The packed bytes array
+ /// @param pointer The pointer to the start of the attestation
+ /// @return attestation The decoded attestation
+ /// @return newPointer The new pointer to the end of the attestation
+ function fromPacked(
+ bytes calldata encoded,
+ uint256 pointer
+ ) internal pure returns (Attestation memory attestation, uint256 newPointer) {
+ newPointer = pointer;
+ (attestation.approvedSigner, newPointer) = encoded.readAddress(newPointer);
+ (attestation.identityType, newPointer) = encoded.readBytes4(newPointer);
+ (attestation.issuerHash, newPointer) = encoded.readBytes32(newPointer);
+ (attestation.audienceHash, newPointer) = encoded.readBytes32(newPointer);
+ // Application data (arbitrary bytes)
+ uint256 dataSize;
+ (dataSize, newPointer) = encoded.readUint24(newPointer);
+ attestation.applicationData = encoded[newPointer:newPointer + dataSize];
+ newPointer += dataSize;
+ // Auth data
+ (attestation.authData, newPointer) = fromPackedAuthData(encoded, newPointer);
+ return (attestation, newPointer);
+ }
+
+ /// @notice Decodes the auth data from a packed bytes
+ /// @param encoded The packed bytes containing the auth data
+ /// @param pointer The pointer to the start of the auth data within the encoded data
+ /// @return authData The decoded auth data
+ /// @return newPointer The pointer to the end of the auth data within the encoded data
+ function fromPackedAuthData(
+ bytes calldata encoded,
+ uint256 pointer
+ ) internal pure returns (AuthData memory authData, uint256 newPointer) {
+ uint24 redirectUrlLength;
+ (redirectUrlLength, pointer) = encoded.readUint24(pointer);
+ authData.redirectUrl = string(encoded[pointer:pointer + redirectUrlLength]);
+ pointer += redirectUrlLength;
+ (authData.issuedAt, pointer) = encoded.readUint64(pointer);
+ return (authData, pointer);
+ }
+
+ /// @notice Encodes an attestation into a packed bytes array
+ /// @param attestation The attestation to encode
+ /// @return encoded The packed bytes array
+ function toPacked(
+ Attestation memory attestation
+ ) internal pure returns (bytes memory encoded) {
+ return abi.encodePacked(
+ attestation.approvedSigner,
+ attestation.identityType,
+ attestation.issuerHash,
+ attestation.audienceHash,
+ uint24(attestation.applicationData.length),
+ attestation.applicationData,
+ toPackAuthData(attestation.authData)
+ );
+ }
+
+ /// @notice Encodes the auth data into a packed bytes array
+ /// @param authData The auth data to encode
+ /// @return encoded The packed bytes array
+ function toPackAuthData(
+ AuthData memory authData
+ ) internal pure returns (bytes memory encoded) {
+ return abi.encodePacked(uint24(bytes(authData.redirectUrl).length), bytes(authData.redirectUrl), authData.issuedAt);
+ }
+
+ /// @notice Generates the implicit request magic return value
+ /// @param attestation The attestation
+ /// @param wallet The wallet
+ /// @return magic The expected implicit request magic
+ function generateImplicitRequestMagic(Attestation memory attestation, address wallet) internal pure returns (bytes32) {
+ return keccak256(
+ abi.encodePacked(ACCEPT_IMPLICIT_REQUEST_MAGIC_PREFIX, wallet, attestation.audienceHash, attestation.issuerHash)
+ );
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/ISignalsImplicitMode.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/ISignalsImplicitMode.sol
new file mode 100644
index 000000000..5ebfc4f50
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/ISignalsImplicitMode.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../../modules/Payload.sol";
+import { Attestation } from "./Attestation.sol";
+
+/// @dev Magic prefix for the implicit request
+bytes32 constant ACCEPT_IMPLICIT_REQUEST_MAGIC_PREFIX = keccak256(abi.encodePacked("acceptImplicitRequest"));
+
+/// @title ISignalsImplicitMode
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Interface for the contracts that support implicit mode validation
+interface ISignalsImplicitMode {
+
+ /// @notice Determines if an implicit request is valid
+ /// @param wallet The wallet's address
+ /// @param attestation The attestation data
+ /// @param call The call to validate
+ /// @return magic The hash of the implicit request if valid
+ function acceptImplicitRequest(
+ address wallet,
+ Attestation calldata attestation,
+ Payload.Call calldata call
+ ) external view returns (bytes32 magic);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/ImplicitSessionManager.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/ImplicitSessionManager.sol
new file mode 100644
index 000000000..0f3ca88a0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/extensions/sessions/implicit/ImplicitSessionManager.sol
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../../modules/Payload.sol";
+
+import { SessionErrors } from "../SessionErrors.sol";
+import { Attestation, LibAttestation } from "./Attestation.sol";
+import { ISignalsImplicitMode } from "./ISignalsImplicitMode.sol";
+
+using LibAttestation for Attestation;
+
+/// @title ImplicitSessionManager
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Manager for implicit sessions
+abstract contract ImplicitSessionManager {
+
+ /// @notice Validates a call in implicit mode
+ /// @param call The call to validate
+ /// @param wallet The wallet's address
+ /// @param sessionSigner The session signer's address
+ /// @param attestation The session attestation
+ function _validateImplicitCall(
+ Payload.Call calldata call,
+ address wallet,
+ address sessionSigner,
+ Attestation memory attestation,
+ address[] memory blacklist
+ ) internal view {
+ // Validate the session signer is attested
+ if (sessionSigner != attestation.approvedSigner) {
+ revert SessionErrors.InvalidSessionSigner(sessionSigner);
+ }
+
+ // Delegate calls are not allowed
+ if (call.delegateCall) {
+ revert SessionErrors.InvalidDelegateCall();
+ }
+ // Check if the signer is blacklisted
+ if (_isAddressBlacklisted(sessionSigner, blacklist)) {
+ revert SessionErrors.BlacklistedAddress(sessionSigner);
+ }
+ // Check if the target address is blacklisted
+ if (_isAddressBlacklisted(call.to, blacklist)) {
+ revert SessionErrors.BlacklistedAddress(call.to);
+ }
+ // No value
+ if (call.value > 0) {
+ revert SessionErrors.InvalidValue();
+ }
+
+ // Validate the implicit request
+ bytes32 result = ISignalsImplicitMode(call.to).acceptImplicitRequest(wallet, attestation, call);
+ bytes32 attestationMagic = attestation.generateImplicitRequestMagic(wallet);
+ if (result != attestationMagic) {
+ revert SessionErrors.InvalidImplicitResult();
+ }
+ }
+
+ /// @notice Checks if an address is in the blacklist using binary search
+ /// @param target The address to check
+ /// @param blacklist The sorted array of blacklisted addresses
+ /// @return bool True if the address is blacklisted, false otherwise
+ function _isAddressBlacklisted(address target, address[] memory blacklist) internal pure returns (bool) {
+ int256 left = 0;
+ int256 right = int256(blacklist.length) - 1;
+
+ while (left <= right) {
+ int256 mid = left + (right - left) / 2;
+ address currentAddress = blacklist[uint256(mid)];
+
+ if (currentAddress == target) {
+ return true;
+ } else if (currentAddress < target) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Calls.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Calls.sol
new file mode 100644
index 000000000..cd3f009a3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Calls.sol
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { LibOptim } from "../utils/LibOptim.sol";
+import { Nonce } from "./Nonce.sol";
+import { Payload } from "./Payload.sol";
+
+import { ReentrancyGuard } from "./ReentrancyGuard.sol";
+import { BaseAuth } from "./auth/BaseAuth.sol";
+import { IDelegatedExtension } from "./interfaces/IDelegatedExtension.sol";
+
+/// @title Calls
+/// @author Agustin Aguilar, Michael Standen, William Hua
+/// @notice Contract for executing calls
+abstract contract Calls is ReentrancyGuard, BaseAuth, Nonce {
+
+ /// @notice Emitted when a call succeeds
+ event CallSucceeded(bytes32 _opHash, uint256 _index);
+ /// @notice Emitted when a call fails
+ event CallFailed(bytes32 _opHash, uint256 _index, bytes _returnData);
+ /// @notice Emitted when a call is aborted
+ event CallAborted(bytes32 _opHash, uint256 _index, bytes _returnData);
+ /// @notice Emitted when a call is skipped
+ event CallSkipped(bytes32 _opHash, uint256 _index);
+
+ /// @notice Error thrown when a call reverts
+ error Reverted(Payload.Decoded _payload, uint256 _index, bytes _returnData);
+ /// @notice Error thrown when a signature is invalid
+ error InvalidSignature(Payload.Decoded _payload, bytes _signature);
+ /// @notice Error thrown when there is not enough gas
+ error NotEnoughGas(Payload.Decoded _payload, uint256 _index, uint256 _gasLeft);
+
+ /// @notice Execute a call
+ /// @param _payload The payload
+ /// @param _signature The signature
+ function execute(bytes calldata _payload, bytes calldata _signature) external payable virtual nonReentrant {
+ uint256 startingGas = gasleft();
+ Payload.Decoded memory decoded = Payload.fromPackedCalls(_payload);
+
+ _consumeNonce(decoded.space, decoded.nonce);
+ (bool isValid, bytes32 opHash) = signatureValidation(decoded, _signature);
+
+ if (!isValid) {
+ revert InvalidSignature(decoded, _signature);
+ }
+
+ _execute(startingGas, opHash, decoded);
+ }
+
+ /// @notice Execute a call
+ /// @dev Callable only by the contract itself
+ /// @param _payload The payload
+ function selfExecute(
+ bytes calldata _payload
+ ) external payable virtual onlySelf {
+ uint256 startingGas = gasleft();
+ Payload.Decoded memory decoded = Payload.fromPackedCalls(_payload);
+ bytes32 opHash = Payload.hash(decoded);
+ _execute(startingGas, opHash, decoded);
+ }
+
+ function _execute(uint256 _startingGas, bytes32 _opHash, Payload.Decoded memory _decoded) private {
+ bool errorFlag = false;
+
+ uint256 numCalls = _decoded.calls.length;
+ for (uint256 i = 0; i < numCalls; i++) {
+ Payload.Call memory call = _decoded.calls[i];
+
+ // Skip onlyFallback calls if no error occurred
+ if (call.onlyFallback && !errorFlag) {
+ emit CallSkipped(_opHash, i);
+ continue;
+ }
+
+ // Reset the error flag
+ // onlyFallback calls only apply when the immediately preceding transaction fails
+ errorFlag = false;
+
+ uint256 gasLimit = call.gasLimit;
+ if (gasLimit != 0 && gasleft() < gasLimit) {
+ revert NotEnoughGas(_decoded, i, gasleft());
+ }
+
+ bool success;
+ if (call.delegateCall) {
+ (success) = LibOptim.delegatecall(
+ call.to,
+ gasLimit == 0 ? gasleft() : gasLimit,
+ abi.encodeWithSelector(
+ IDelegatedExtension.handleSequenceDelegateCall.selector,
+ _opHash,
+ _startingGas,
+ i,
+ numCalls,
+ _decoded.space,
+ call.data
+ )
+ );
+ } else {
+ (success) = LibOptim.call(call.to, call.value, gasLimit == 0 ? gasleft() : gasLimit, call.data);
+ }
+
+ if (!success) {
+ if (call.behaviorOnError == Payload.BEHAVIOR_IGNORE_ERROR) {
+ errorFlag = true;
+ emit CallFailed(_opHash, i, LibOptim.returnData());
+ continue;
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_REVERT_ON_ERROR) {
+ revert Reverted(_decoded, i, LibOptim.returnData());
+ }
+
+ if (call.behaviorOnError == Payload.BEHAVIOR_ABORT_ON_ERROR) {
+ emit CallAborted(_opHash, i, LibOptim.returnData());
+ break;
+ }
+ }
+
+ emit CallSucceeded(_opHash, i);
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/ERC4337v07.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/ERC4337v07.sol
new file mode 100644
index 000000000..d8c100968
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/ERC4337v07.sol
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+import { Calls } from "./Calls.sol";
+
+import { ReentrancyGuard } from "./ReentrancyGuard.sol";
+import { IAccount, PackedUserOperation } from "./interfaces/IAccount.sol";
+import { IERC1271_MAGIC_VALUE_HASH } from "./interfaces/IERC1271.sol";
+import { IEntryPoint } from "./interfaces/IEntryPoint.sol";
+
+/// @title ERC4337v07
+/// @author Agustin Aguilar, Michael Standen
+/// @notice ERC4337 v7 support
+abstract contract ERC4337v07 is ReentrancyGuard, IAccount, Calls {
+
+ uint256 internal constant SIG_VALIDATION_FAILED = 1;
+
+ address public immutable entrypoint;
+
+ error InvalidEntryPoint(address _entrypoint);
+ error ERC4337Disabled();
+
+ constructor(
+ address _entrypoint
+ ) {
+ entrypoint = _entrypoint;
+ }
+
+ /// @inheritdoc IAccount
+ function validateUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingAccountFunds
+ ) external returns (uint256 validationData) {
+ if (entrypoint == address(0)) {
+ revert ERC4337Disabled();
+ }
+
+ if (msg.sender != entrypoint) {
+ revert InvalidEntryPoint(msg.sender);
+ }
+
+ // userOp.nonce is validated by the entrypoint
+
+ if (missingAccountFunds != 0) {
+ IEntryPoint(entrypoint).depositTo{ value: missingAccountFunds }(address(this));
+ }
+
+ if (this.isValidSignature(userOpHash, userOp.signature) != IERC1271_MAGIC_VALUE_HASH) {
+ return SIG_VALIDATION_FAILED;
+ }
+
+ return 0;
+ }
+
+ /// @notice Execute a user operation
+ /// @param _payload The packed payload
+ /// @dev This is the execute function for the EntryPoint to call.
+ function executeUserOp(
+ bytes calldata _payload
+ ) external nonReentrant {
+ if (entrypoint == address(0)) {
+ revert ERC4337Disabled();
+ }
+
+ if (msg.sender != entrypoint) {
+ revert InvalidEntryPoint(msg.sender);
+ }
+
+ this.selfExecute(_payload);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Hooks.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Hooks.sol
new file mode 100644
index 000000000..ca0e1fabc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Hooks.sol
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Storage } from "./Storage.sol";
+import { SelfAuth } from "./auth/SelfAuth.sol";
+import { IERC1155Receiver } from "./interfaces/IERC1155Receiver.sol";
+import { IERC223Receiver } from "./interfaces/IERC223Receiver.sol";
+import { IERC721Receiver } from "./interfaces/IERC721Receiver.sol";
+import { IERC777Receiver } from "./interfaces/IERC777Receiver.sol";
+
+/// @title Hooks
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Enables extension of the wallet by adding hooks
+contract Hooks is SelfAuth, IERC1155Receiver, IERC777Receiver, IERC721Receiver, IERC223Receiver {
+
+ /// @dev keccak256("org.arcadeum.module.hooks.hooks")
+ bytes32 private constant HOOKS_KEY = bytes32(0xbe27a319efc8734e89e26ba4bc95f5c788584163b959f03fa04e2d7ab4b9a120);
+
+ /// @notice Emitted when a hook is defined
+ event DefinedHook(bytes4 selector, address implementation);
+
+ /// @notice Error thrown when a hook already exists
+ error HookAlreadyExists(bytes4 selector);
+ /// @notice Error thrown when a hook does not exist
+ error HookDoesNotExist(bytes4 selector);
+
+ /// @notice Read a hook
+ /// @param selector The selector of the hook
+ /// @return implementation The implementation address of the hook
+ function readHook(
+ bytes4 selector
+ ) external view returns (address) {
+ return _readHook(selector);
+ }
+
+ /// @notice Add a hook
+ /// @param selector The selector of the hook
+ /// @param implementation The implementation address of the hook
+ /// @dev Callable only by the contract itself
+ function addHook(bytes4 selector, address implementation) external payable onlySelf {
+ if (_readHook(selector) != address(0)) {
+ revert HookAlreadyExists(selector);
+ }
+ _writeHook(selector, implementation);
+ }
+
+ /// @notice Remove a hook
+ /// @param selector The selector of the hook
+ /// @dev Callable only by the contract itself
+ function removeHook(
+ bytes4 selector
+ ) external payable onlySelf {
+ if (_readHook(selector) == address(0)) {
+ revert HookDoesNotExist(selector);
+ }
+ _writeHook(selector, address(0));
+ }
+
+ function _readHook(
+ bytes4 selector
+ ) private view returns (address) {
+ return address(uint160(uint256(Storage.readBytes32Map(HOOKS_KEY, bytes32(selector)))));
+ }
+
+ function _writeHook(bytes4 selector, address implementation) private {
+ Storage.writeBytes32Map(HOOKS_KEY, bytes32(selector), bytes32(uint256(uint160(implementation))));
+ emit DefinedHook(selector, implementation);
+ }
+
+ /// @inheritdoc IERC1155Receiver
+ function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) {
+ return Hooks.onERC1155Received.selector;
+ }
+
+ /// @inheritdoc IERC1155Receiver
+ function onERC1155BatchReceived(
+ address,
+ address,
+ uint256[] calldata,
+ uint256[] calldata,
+ bytes calldata
+ ) external pure returns (bytes4) {
+ return Hooks.onERC1155BatchReceived.selector;
+ }
+
+ /// @inheritdoc IERC777Receiver
+ function tokensReceived(
+ address operator,
+ address from,
+ address to,
+ uint256 amount,
+ bytes calldata data,
+ bytes calldata operatorData
+ ) external { }
+
+ /// @inheritdoc IERC721Receiver
+ function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
+ return Hooks.onERC721Received.selector;
+ }
+
+ /// @inheritdoc IERC223Receiver
+ function tokenReceived(address, uint256, bytes calldata) external pure returns (bytes4) {
+ return Hooks.tokenReceived.selector;
+ }
+
+ /// @notice Fallback function
+ /// @dev Handles delegate calls to hooks
+ fallback() external payable {
+ if (msg.data.length >= 4) {
+ address target = _readHook(bytes4(msg.data));
+ if (target != address(0)) {
+ (bool success, bytes memory result) = target.delegatecall(msg.data);
+ assembly {
+ if iszero(success) { revert(add(result, 32), mload(result)) }
+ return(add(result, 32), mload(result))
+ }
+ }
+ }
+ }
+
+ /// @notice Receive native tokens
+ receive() external payable { }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Implementation.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Implementation.sol
new file mode 100644
index 000000000..99f7a9442
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Implementation.sol
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { SelfAuth } from "./auth/SelfAuth.sol";
+
+/// @title Implementation
+/// @author Agustin Aguilar
+/// @notice Manages the implementation address of the proxy contract
+contract Implementation is SelfAuth {
+
+ /// @notice Emitted when the implementation is updated
+ event ImplementationUpdated(address newImplementation);
+
+ /// @notice Update the implementation
+ /// @param _implementation The new implementation
+ /// @dev Callable only by the contract itself
+ function updateImplementation(
+ address _implementation
+ ) external payable virtual onlySelf {
+ _updateImplementation(_implementation);
+ }
+
+ /// @notice Get the implementation
+ /// @return implementation The implementation
+ function getImplementation() external view virtual returns (address) {
+ return _getImplementation();
+ }
+
+ function _updateImplementation(
+ address _implementation
+ ) internal virtual {
+ _setImplementation(_implementation);
+ emit ImplementationUpdated(_implementation);
+ }
+
+ function _setImplementation(
+ address _imp
+ ) internal {
+ assembly {
+ sstore(address(), _imp)
+ }
+ }
+
+ function _getImplementation() internal view returns (address _imp) {
+ assembly {
+ _imp := sload(address())
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Nonce.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Nonce.sol
new file mode 100644
index 000000000..2fbf587a4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Nonce.sol
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Storage } from "./Storage.sol";
+
+/// @title Nonce
+/// @author Agustin Aguilar
+/// @notice Manages the nonce of the wallet
+contract Nonce {
+
+ /// @notice Emitted when the nonce is changed
+ event NonceChange(uint256 _space, uint256 _newNonce);
+
+ /// @notice Error thrown when the nonce is bad
+ error BadNonce(uint256 _space, uint256 _provided, uint256 _current);
+
+ /// @dev keccak256("org.arcadeum.module.calls.nonce")
+ bytes32 private constant NONCE_KEY = bytes32(0x8d0bf1fd623d628c741362c1289948e57b3e2905218c676d3e69abee36d6ae2e);
+
+ /// @notice Read the nonce
+ /// @param _space The space
+ /// @return nonce The nonce
+ function readNonce(
+ uint256 _space
+ ) public view virtual returns (uint256) {
+ return uint256(Storage.readBytes32Map(NONCE_KEY, bytes32(_space)));
+ }
+
+ function _writeNonce(uint256 _space, uint256 _nonce) internal {
+ Storage.writeBytes32Map(NONCE_KEY, bytes32(_space), bytes32(_nonce));
+ }
+
+ function _consumeNonce(uint256 _space, uint256 _nonce) internal {
+ uint256 currentNonce = readNonce(_space);
+ if (currentNonce != _nonce) {
+ revert BadNonce(_space, _nonce, currentNonce);
+ }
+
+ unchecked {
+ uint256 newNonce = _nonce + 1;
+
+ _writeNonce(_space, newNonce);
+ emit NonceChange(_space, newNonce);
+ return;
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Payload.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Payload.sol
new file mode 100644
index 000000000..18e611038
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Payload.sol
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { LibBytes } from "../utils/LibBytes.sol";
+
+using LibBytes for bytes;
+
+/// @title Payload
+/// @author Agustin Aguilar, Michael Standen, William Hua
+/// @notice Library for encoding and decoding payloads
+library Payload {
+
+ /// @notice Error thrown when the kind is invalid
+ error InvalidKind(uint8 kind);
+
+ /// @dev keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
+ bytes32 private constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
+
+ /// @dev keccak256("Sequence Wallet")
+ bytes32 private constant EIP712_DOMAIN_NAME_SEQUENCE =
+ 0x4aa45ca7ad825ceb1bf35643f0a58c295239df563b1b565c2485f96477c56318;
+
+ /// @dev keccak256("3")
+ bytes32 private constant EIP712_DOMAIN_VERSION_SEQUENCE =
+ 0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de;
+
+ function domainSeparator(bool _noChainId, address _wallet) internal view returns (bytes32 _domainSeparator) {
+ return keccak256(
+ abi.encode(
+ EIP712_DOMAIN_TYPEHASH,
+ EIP712_DOMAIN_NAME_SEQUENCE,
+ EIP712_DOMAIN_VERSION_SEQUENCE,
+ _noChainId ? uint256(0) : uint256(block.chainid),
+ _wallet
+ )
+ );
+ }
+
+ /// @dev keccak256("Call(address to,uint256 value,bytes data,uint256 gasLimit,bool delegateCall,bool onlyFallback,uint256 behaviorOnError)")
+ bytes32 private constant CALL_TYPEHASH = 0x0603985259a953da1f65a522f589c17bd1d0117ec1d3abb7c0788aef251ef437;
+
+ /// @dev keccak256("Calls(Call[] calls,uint256 space,uint256 nonce,address[] wallets)Call(address to,uint256 value,bytes data,uint256 gasLimit,bool delegateCall,bool onlyFallback,uint256 behaviorOnError)")
+ bytes32 private constant CALLS_TYPEHASH = 0x11e1e4079a79a66e4ade50033cfe2678cdd5341d2dfe5ef9513edb1a0be147a2;
+
+ /// @dev keccak256("Message(bytes message,address[] wallets)")
+ bytes32 private constant MESSAGE_TYPEHASH = 0xe19a3b94fc3c7ece3f890d98a99bc422615537a08dea0603fa8425867d87d466;
+
+ /// @dev keccak256("ConfigUpdate(bytes32 imageHash,address[] wallets)")
+ bytes32 private constant CONFIG_UPDATE_TYPEHASH = 0x11fdeb7e8373a1aa96bfac8d0ea91526b2c5d15e5cee20e0543e780258f3e8e4;
+
+ /// @notice Kind of transaction
+ uint8 public constant KIND_TRANSACTIONS = 0x00;
+ /// @notice Kind of digest
+ uint8 public constant KIND_MESSAGE = 0x01;
+ /// @notice Kind of config update
+ uint8 public constant KIND_CONFIG_UPDATE = 0x02;
+ /// @notice Kind of message
+ uint8 public constant KIND_DIGEST = 0x03;
+
+ /// @notice Behavior on error: ignore error
+ uint8 public constant BEHAVIOR_IGNORE_ERROR = 0x00;
+ /// @notice Behavior on error: revert on error
+ uint8 public constant BEHAVIOR_REVERT_ON_ERROR = 0x01;
+ /// @notice Behavior on error: abort on error
+ uint8 public constant BEHAVIOR_ABORT_ON_ERROR = 0x02;
+
+ /// @notice Payload call information
+ /// @param to Address of the target contract
+ /// @param value Value to send with the call
+ /// @param data Data to send with the call
+ /// @param gasLimit Gas limit for the call
+ /// @param delegateCall If the call is a delegate call
+ /// @param onlyFallback If the call should only be executed in an error scenario
+ /// @param behaviorOnError Behavior on error
+ struct Call {
+ address to;
+ uint256 value;
+ bytes data;
+ uint256 gasLimit;
+ bool delegateCall;
+ bool onlyFallback;
+ uint256 behaviorOnError;
+ }
+
+ /// @notice Decoded payload
+ /// @param kind Kind of payload
+ /// @param noChainId If the chain ID should be omitted
+ /// @param calls Array of calls (transaction kind)
+ /// @param space Nonce space for the calls (transaction kind)
+ /// @param nonce Nonce value for the calls (transaction kind)
+ /// @param message Message to validate (message kind)
+ /// @param imageHash Image hash to update to (config update kind)
+ /// @param digest Digest to validate (digest kind)
+ /// @param parentWallets Parent wallets
+ struct Decoded {
+ uint8 kind;
+ bool noChainId;
+ // Transaction kind
+ Call[] calls;
+ uint256 space;
+ uint256 nonce;
+ // Message kind
+ bytes message;
+ // Config update kind
+ bytes32 imageHash;
+ // Digest kind for 1271
+ bytes32 digest;
+ // Parent wallets
+ address[] parentWallets;
+ }
+
+ function fromMessage(
+ bytes memory message
+ ) internal pure returns (Decoded memory _decoded) {
+ _decoded.kind = KIND_MESSAGE;
+ _decoded.message = message;
+ }
+
+ function fromConfigUpdate(
+ bytes32 imageHash
+ ) internal pure returns (Decoded memory _decoded) {
+ _decoded.kind = KIND_CONFIG_UPDATE;
+ _decoded.imageHash = imageHash;
+ }
+
+ function fromDigest(
+ bytes32 digest
+ ) internal pure returns (Decoded memory _decoded) {
+ _decoded.kind = KIND_DIGEST;
+ _decoded.digest = digest;
+ }
+
+ function fromPackedCalls(
+ bytes calldata packed
+ ) internal view returns (Decoded memory _decoded) {
+ _decoded.kind = KIND_TRANSACTIONS;
+
+ // Read the global flag
+ (uint256 globalFlag, uint256 pointer) = packed.readFirstUint8();
+
+ // First bit determines if space is zero or not
+ if (globalFlag & 0x01 == 0x01) {
+ _decoded.space = 0;
+ } else {
+ (_decoded.space, pointer) = packed.readUint160(pointer);
+ }
+
+ // Next 3 bits determine the size of the nonce
+ uint256 nonceSize = (globalFlag >> 1) & 0x07;
+
+ if (nonceSize > 0) {
+ // Read the nonce
+ (_decoded.nonce, pointer) = packed.readUintX(pointer, nonceSize);
+ }
+
+ uint256 numCalls;
+
+ // Bit 5 determines if the batch contains a single call
+ if (globalFlag & 0x10 == 0x10) {
+ numCalls = 1;
+ } else {
+ // Bit 6 determines if the number of calls uses 1 byte or 2 bytes
+ if (globalFlag & 0x20 == 0x20) {
+ (numCalls, pointer) = packed.readUint16(pointer);
+ } else {
+ (numCalls, pointer) = packed.readUint8(pointer);
+ }
+ }
+
+ // Read the calls
+ _decoded.calls = new Call[](numCalls);
+
+ for (uint256 i = 0; i < numCalls; i++) {
+ uint8 flags;
+ (flags, pointer) = packed.readUint8(pointer);
+
+ // First bit determines if this is a call to self
+ // or a call to another address
+ if (flags & 0x01 == 0x01) {
+ // Call to self
+ _decoded.calls[i].to = address(this);
+ } else {
+ // Call to another address
+ (_decoded.calls[i].to, pointer) = packed.readAddress(pointer);
+ }
+
+ // Second bit determines if the call has value or not
+ if (flags & 0x02 == 0x02) {
+ (_decoded.calls[i].value, pointer) = packed.readUint256(pointer);
+ }
+
+ // Third bit determines if the call has data or not
+ if (flags & 0x04 == 0x04) {
+ // 3 bytes determine the size of the calldata
+ uint256 calldataSize;
+ (calldataSize, pointer) = packed.readUint24(pointer);
+ _decoded.calls[i].data = packed[pointer:pointer + calldataSize];
+ pointer += calldataSize;
+ }
+
+ // Fourth bit determines if the call has a gas limit or not
+ if (flags & 0x08 == 0x08) {
+ (_decoded.calls[i].gasLimit, pointer) = packed.readUint256(pointer);
+ }
+
+ // Fifth bit determines if the call is a delegate call or not
+ _decoded.calls[i].delegateCall = (flags & 0x10 == 0x10);
+
+ // Sixth bit determines if the call is fallback only
+ _decoded.calls[i].onlyFallback = (flags & 0x20 == 0x20);
+
+ // Last 2 bits are directly mapped to the behavior on error
+ _decoded.calls[i].behaviorOnError = (flags & 0xC0) >> 6;
+ }
+ }
+
+ function hashCall(
+ Call memory c
+ ) internal pure returns (bytes32) {
+ return keccak256(
+ abi.encode(
+ CALL_TYPEHASH, c.to, c.value, keccak256(c.data), c.gasLimit, c.delegateCall, c.onlyFallback, c.behaviorOnError
+ )
+ );
+ }
+
+ function hashCalls(
+ Call[] memory calls
+ ) internal pure returns (bytes32) {
+ // In EIP712, an array is often hashed as the keccak256 of the concatenated
+ // hashes of each item. So we hash each Call, pack them, and hash again.
+ bytes32[] memory callHashes = new bytes32[](calls.length);
+ for (uint256 i = 0; i < calls.length; i++) {
+ callHashes[i] = hashCall(calls[i]);
+ }
+ return keccak256(abi.encodePacked(callHashes));
+ }
+
+ function toEIP712(
+ Decoded memory _decoded
+ ) internal pure returns (bytes32) {
+ bytes32 walletsHash = keccak256(abi.encodePacked(_decoded.parentWallets));
+
+ if (_decoded.kind == KIND_TRANSACTIONS) {
+ bytes32 callsHash = hashCalls(_decoded.calls);
+ // The top-level struct for Calls might be something like:
+ // Calls(bytes32 callsHash,uint256 space,uint256 nonce,bytes32 walletsHash)
+ return keccak256(abi.encode(CALLS_TYPEHASH, callsHash, _decoded.space, _decoded.nonce, walletsHash));
+ } else if (_decoded.kind == KIND_MESSAGE) {
+ // If you define your top-level as: Message(bytes32 messageHash,bytes32 walletsHash)
+ return keccak256(abi.encode(MESSAGE_TYPEHASH, keccak256(_decoded.message), walletsHash));
+ } else if (_decoded.kind == KIND_CONFIG_UPDATE) {
+ // Top-level: ConfigUpdate(bytes32 imageHash,bytes32 walletsHash)
+ return keccak256(abi.encode(CONFIG_UPDATE_TYPEHASH, _decoded.imageHash, walletsHash));
+ } else if (_decoded.kind == KIND_DIGEST) {
+ // Top-level: Use MESSAGE_TYPEHASH but assume the digest is already the hashed message
+ return keccak256(abi.encode(MESSAGE_TYPEHASH, _decoded.digest, walletsHash));
+ } else {
+ // Unknown kind
+ revert InvalidKind(_decoded.kind);
+ }
+ }
+
+ function hash(
+ Decoded memory _decoded
+ ) internal view returns (bytes32) {
+ bytes32 domain = domainSeparator(_decoded.noChainId, address(this));
+ bytes32 structHash = toEIP712(_decoded);
+ return keccak256(abi.encodePacked("\x19\x01", domain, structHash));
+ }
+
+ function hashFor(Decoded memory _decoded, address _wallet) internal view returns (bytes32) {
+ bytes32 domain = domainSeparator(_decoded.noChainId, _wallet);
+ bytes32 structHash = toEIP712(_decoded);
+ return keccak256(abi.encodePacked("\x19\x01", domain, structHash));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/ReentrancyGuard.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/ReentrancyGuard.sol
new file mode 100644
index 000000000..2397605de
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/ReentrancyGuard.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import { Storage } from "./Storage.sol";
+
+abstract contract ReentrancyGuard {
+
+ bytes32 private constant _INITIAL_VALUE = bytes32(0);
+ bytes32 private constant _NOT_ENTERED = bytes32(uint256(1));
+ bytes32 private constant _ENTERED = bytes32(uint256(2));
+
+ /// @dev keccak256("org.sequence.module.reentrancyguard.status")
+ bytes32 private constant STATUS_KEY = bytes32(0xfc6e07e3992c7c3694a921dc9e412b6cfe475380556756a19805a9e3ddfe2fde);
+
+ /// @notice Error thrown when a reentrant call is detected
+ error ReentrantCall();
+
+ /// @notice Prevents a contract from calling itself, directly or indirectly
+ modifier nonReentrant() {
+ // On the first call to nonReentrant
+ // _status will be _NOT_ENTERED or _INITIAL_VALUE
+ if (Storage.readBytes32(STATUS_KEY) == _ENTERED) {
+ revert ReentrantCall();
+ }
+
+ // Any calls to nonReentrant after this point will fail
+ Storage.writeBytes32(STATUS_KEY, _ENTERED);
+
+ _;
+
+ // By storing the original value once again, a refund is triggered (see
+ // https://eips.ethereum.org/EIPS/eip-2200)
+ // Notice that because constructors are not available
+ // we always start with _INITIAL_VALUE, not _NOT_ENTERED
+ Storage.writeBytes32(STATUS_KEY, _NOT_ENTERED);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Storage.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Storage.sol
new file mode 100644
index 000000000..f340afbbe
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/Storage.sol
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+/// @title Storage
+/// @author Agustin Aguilar
+/// @notice Library for storing data at certain storage slots
+library Storage {
+
+ function writeBytes32(bytes32 _key, bytes32 _val) internal {
+ assembly {
+ sstore(_key, _val)
+ }
+ }
+
+ function readBytes32(
+ bytes32 _key
+ ) internal view returns (bytes32 val) {
+ assembly {
+ val := sload(_key)
+ }
+ }
+
+ function writeBytes32Map(bytes32 _key, bytes32 _subKey, bytes32 _val) internal {
+ bytes32 key = keccak256(abi.encode(_key, _subKey));
+ assembly {
+ sstore(key, _val)
+ }
+ }
+
+ function readBytes32Map(bytes32 _key, bytes32 _subKey) internal view returns (bytes32 val) {
+ bytes32 key = keccak256(abi.encode(_key, _subKey));
+ assembly {
+ val := sload(key)
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/BaseAuth.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/BaseAuth.sol
new file mode 100644
index 000000000..b3b2bf0e8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/BaseAuth.sol
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../Payload.sol";
+
+import { Storage } from "../Storage.sol";
+import { IAuth } from "../interfaces/IAuth.sol";
+import { IERC1271, IERC1271_MAGIC_VALUE_HASH } from "../interfaces/IERC1271.sol";
+
+import { IPartialAuth } from "../interfaces/IPartialAuth.sol";
+import { ISapient } from "../interfaces/ISapient.sol";
+import { BaseSig } from "./BaseSig.sol";
+
+import { SelfAuth } from "./SelfAuth.sol";
+
+using Payload for Payload.Decoded;
+
+/// @title BaseAuth
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Base contract for the auth module
+abstract contract BaseAuth is IAuth, IPartialAuth, ISapient, IERC1271, SelfAuth {
+
+ /// @dev keccak256("org.sequence.module.auth.static")
+ bytes32 private constant STATIC_SIGNATURE_KEY =
+ bytes32(0xc852adf5e97c2fc3b38f405671e91b7af1697ef0287577f227ef10494c2a8e86);
+
+ /// @notice Error thrown when the sapient signature is invalid
+ error InvalidSapientSignature(Payload.Decoded _payload, bytes _signature);
+ /// @notice Error thrown when the signature weight is invalid
+ error InvalidSignatureWeight(uint256 _threshold, uint256 _weight);
+ /// @notice Error thrown when the static signature has expired
+ error InvalidStaticSignatureExpired(bytes32 _opHash, uint256 _expires);
+ /// @notice Error thrown when the static signature has the wrong caller
+ error InvalidStaticSignatureWrongCaller(bytes32 _opHash, address _caller, address _expectedCaller);
+
+ /// @notice Event emitted when a static signature is set
+ event StaticSignatureSet(bytes32 _hash, address _address, uint96 _timestamp);
+
+ function _getStaticSignature(
+ bytes32 _hash
+ ) internal view returns (address, uint256) {
+ uint256 word = uint256(Storage.readBytes32Map(STATIC_SIGNATURE_KEY, _hash));
+ return (address(uint160(word >> 96)), uint256(uint96(word)));
+ }
+
+ function _setStaticSignature(bytes32 _hash, address _address, uint256 _timestamp) internal {
+ Storage.writeBytes32Map(
+ STATIC_SIGNATURE_KEY, _hash, bytes32(uint256(uint160(_address)) << 96 | (_timestamp & 0xffffffffffffffffffffffff))
+ );
+ }
+
+ /// @notice Get the static signature for a specific hash
+ /// @param _hash The hash to get the static signature for
+ /// @return address The address associated with the static signature
+ /// @return timestamp The timestamp of the static signature
+ function getStaticSignature(
+ bytes32 _hash
+ ) external view returns (address, uint256) {
+ return _getStaticSignature(_hash);
+ }
+
+ /// @notice Set the static signature for a specific hash
+ /// @param _hash The hash to set the static signature for
+ /// @param _address The address to associate with the static signature
+ /// @param _timestamp The timestamp of the static signature
+ /// @dev Only callable by the wallet itself
+ function setStaticSignature(bytes32 _hash, address _address, uint96 _timestamp) external onlySelf {
+ _setStaticSignature(_hash, _address, _timestamp);
+ emit StaticSignatureSet(_hash, _address, _timestamp);
+ }
+
+ /// @notice Update the image hash
+ /// @param _imageHash The new image hash
+ /// @dev Only callable by the wallet itself
+ function updateImageHash(
+ bytes32 _imageHash
+ ) external virtual onlySelf {
+ _updateImageHash(_imageHash);
+ }
+
+ function signatureValidation(
+ Payload.Decoded memory _payload,
+ bytes calldata _signature
+ ) internal view virtual returns (bool isValid, bytes32 opHash) {
+ // Read first bit to determine if static signature is used
+ bytes1 signatureFlag = _signature[0];
+
+ if (signatureFlag & 0x80 == 0x80) {
+ opHash = _payload.hash();
+
+ (address addr, uint256 timestamp) = _getStaticSignature(opHash);
+ if (timestamp <= block.timestamp) {
+ revert InvalidStaticSignatureExpired(opHash, timestamp);
+ }
+
+ if (addr != address(0) && addr != msg.sender) {
+ revert InvalidStaticSignatureWrongCaller(opHash, msg.sender, addr);
+ }
+
+ return (true, opHash);
+ }
+
+ // Static signature is not used, recover and validate imageHash
+
+ uint256 threshold;
+ uint256 weight;
+ bytes32 imageHash;
+
+ (threshold, weight, imageHash,, opHash) = BaseSig.recover(_payload, _signature, false, address(0));
+
+ // Validate the weight
+ if (weight < threshold) {
+ revert InvalidSignatureWeight(threshold, weight);
+ }
+
+ isValid = _isValidImage(imageHash);
+ }
+
+ /// @inheritdoc ISapient
+ function recoverSapientSignature(
+ Payload.Decoded memory _payload,
+ bytes calldata _signature
+ ) external view returns (bytes32) {
+ // Copy parent wallets + add caller at the end
+ address[] memory parentWallets = new address[](_payload.parentWallets.length + 1);
+
+ for (uint256 i = 0; i < _payload.parentWallets.length; i++) {
+ parentWallets[i] = _payload.parentWallets[i];
+ }
+
+ parentWallets[_payload.parentWallets.length] = msg.sender;
+ _payload.parentWallets = parentWallets;
+
+ (bool isValid,) = signatureValidation(_payload, _signature);
+ if (!isValid) {
+ revert InvalidSapientSignature(_payload, _signature);
+ }
+
+ return bytes32(uint256(1));
+ }
+
+ /// @inheritdoc IERC1271
+ function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4) {
+ Payload.Decoded memory payload = Payload.fromDigest(_hash);
+
+ (bool isValid,) = signatureValidation(payload, _signature);
+ if (!isValid) {
+ return bytes4(0);
+ }
+
+ return IERC1271_MAGIC_VALUE_HASH;
+ }
+
+ /// @inheritdoc IPartialAuth
+ function recoverPartialSignature(
+ Payload.Decoded memory _payload,
+ bytes calldata _signature
+ )
+ external
+ view
+ returns (
+ uint256 threshold,
+ uint256 weight,
+ bool isValidImage,
+ bytes32 imageHash,
+ uint256 checkpoint,
+ bytes32 opHash
+ )
+ {
+ (threshold, weight, imageHash, checkpoint, opHash) = BaseSig.recover(_payload, _signature, false, address(0));
+ isValidImage = _isValidImage(imageHash);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/BaseSig.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/BaseSig.sol
new file mode 100644
index 000000000..a43340ac5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/BaseSig.sol
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { LibBytes } from "../../utils/LibBytes.sol";
+import { LibOptim } from "../../utils/LibOptim.sol";
+import { Payload } from "../Payload.sol";
+
+import { ICheckpointer, Snapshot } from "../interfaces/ICheckpointer.sol";
+import { IERC1271, IERC1271_MAGIC_VALUE_HASH } from "../interfaces/IERC1271.sol";
+import { ISapient, ISapientCompact } from "../interfaces/ISapient.sol";
+
+using LibBytes for bytes;
+using Payload for Payload.Decoded;
+
+/// @title BaseSig
+/// @author Agustin Aguilar, Michael Standen, William Hua, Shun Kakinoki
+/// @notice Library for recovering signatures from the base-auth payload
+library BaseSig {
+
+ uint256 internal constant FLAG_SIGNATURE_HASH = 0;
+ uint256 internal constant FLAG_ADDRESS = 1;
+ uint256 internal constant FLAG_SIGNATURE_ERC1271 = 2;
+ uint256 internal constant FLAG_NODE = 3;
+ uint256 internal constant FLAG_BRANCH = 4;
+ uint256 internal constant FLAG_SUBDIGEST = 5;
+ uint256 internal constant FLAG_NESTED = 6;
+ uint256 internal constant FLAG_SIGNATURE_ETH_SIGN = 7;
+ uint256 internal constant FLAG_SIGNATURE_ANY_ADDRESS_SUBDIGEST = 8;
+ uint256 internal constant FLAG_SIGNATURE_SAPIENT = 9;
+ uint256 internal constant FLAG_SIGNATURE_SAPIENT_COMPACT = 10;
+
+ /// @notice Error thrown when the weight is too low for a chained signature
+ error LowWeightChainedSignature(bytes _signature, uint256 _threshold, uint256 _weight);
+ /// @notice Error thrown when the ERC1271 signature is invalid
+ error InvalidERC1271Signature(bytes32 _opHash, address _signer, bytes _signature);
+ /// @notice Error thrown when the checkpoint order is wrong
+ error WrongChainedCheckpointOrder(uint256 _nextCheckpoint, uint256 _checkpoint);
+ /// @notice Error thrown when the snapshot is unused
+ error UnusedSnapshot(Snapshot _snapshot);
+ /// @notice Error thrown when the signature flag is invalid
+ error InvalidSignatureFlag(uint256 _flag);
+
+ function _leafForAddressAndWeight(address _addr, uint256 _weight) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked("Sequence signer:\n", _addr, _weight));
+ }
+
+ function _leafForNested(bytes32 _node, uint256 _threshold, uint256 _weight) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked("Sequence nested config:\n", _node, _threshold, _weight));
+ }
+
+ function _leafForSapient(address _addr, uint256 _weight, bytes32 _imageHash) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked("Sequence sapient config:\n", _addr, _weight, _imageHash));
+ }
+
+ function _leafForHardcodedSubdigest(
+ bytes32 _subdigest
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked("Sequence static digest:\n", _subdigest));
+ }
+
+ function _leafForAnyAddressSubdigest(
+ bytes32 _anyAddressSubdigest
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked("Sequence any address subdigest:\n", _anyAddressSubdigest));
+ }
+
+ function recover(
+ Payload.Decoded memory _payload,
+ bytes calldata _signature,
+ bool _ignoreCheckpointer,
+ address _checkpointer
+ ) internal view returns (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) {
+ // First byte is the signature flag
+ (uint256 signatureFlag, uint256 rindex) = _signature.readFirstUint8();
+
+ // The possible flags are:
+ // - 0000 00XX (bits [1..0]): signature type (00 = normal, 01/11 = chained, 10 = no chain id)
+ // - 000X XX00 (bits [4..2]): checkpoint size (00 = 0 bytes, 001 = 1 byte, 010 = 2 bytes...)
+ // - 00X0 0000 (bit [5]): threshold size (0 = 1 byte, 1 = 2 bytes)
+ // - 0X00 0000 (bit [6]): set if imageHash checkpointer is used
+ // - X000 0000 (bit [7]): reserved by base-auth
+
+ Snapshot memory snapshot;
+
+ // Recover the imageHash checkpointer if any
+ // but checkpointer passed as argument takes precedence
+ // since it can be defined by the chained signatures
+ if (signatureFlag & 0x40 == 0x40 && _checkpointer == address(0)) {
+ // Override the checkpointer
+ // not ideal, but we don't have much room in the stack
+ (_checkpointer, rindex) = _signature.readAddress(rindex);
+
+ if (!_ignoreCheckpointer) {
+ // Next 3 bytes determine the checkpointer data size
+ uint256 checkpointerDataSize;
+ (checkpointerDataSize, rindex) = _signature.readUint24(rindex);
+
+ // Read the checkpointer data
+ bytes memory checkpointerData = _signature[rindex:rindex + checkpointerDataSize];
+
+ // Call the middleware
+ snapshot = ICheckpointer(_checkpointer).snapshotFor(address(this), checkpointerData);
+
+ rindex += checkpointerDataSize;
+ }
+ }
+
+ // If signature type is 01 or 11 we do a chained signature
+ if (signatureFlag & 0x01 == 0x01) {
+ return recoverChained(_payload, _checkpointer, snapshot, _signature[rindex:]);
+ }
+
+ // If the signature type is 10 we do a no chain id signature
+ _payload.noChainId = signatureFlag & 0x02 == 0x02;
+
+ {
+ // Recover the checkpoint using the size defined by the flag
+ uint256 checkpointSize = (signatureFlag & 0x1c) >> 2;
+ (checkpoint, rindex) = _signature.readUintX(rindex, checkpointSize);
+ }
+
+ // Recover the threshold, using the flag for the size
+ {
+ uint256 thresholdSize = ((signatureFlag & 0x20) >> 5) + 1;
+ (threshold, rindex) = _signature.readUintX(rindex, thresholdSize);
+ }
+
+ // Recover the tree
+ opHash = _payload.hash();
+ (weight, imageHash) = recoverBranch(_payload, opHash, _signature[rindex:]);
+
+ imageHash = LibOptim.fkeccak256(imageHash, bytes32(threshold));
+ imageHash = LibOptim.fkeccak256(imageHash, bytes32(checkpoint));
+ imageHash = LibOptim.fkeccak256(imageHash, bytes32(uint256(uint160(_checkpointer))));
+
+ // If the snapshot is used, either the imageHash must match
+ // or the checkpoint must be greater than the snapshot checkpoint
+ if (snapshot.imageHash != bytes32(0) && snapshot.imageHash != imageHash && checkpoint <= snapshot.checkpoint) {
+ revert UnusedSnapshot(snapshot);
+ }
+ }
+
+ function recoverChained(
+ Payload.Decoded memory _payload,
+ address _checkpointer,
+ Snapshot memory _snapshot,
+ bytes calldata _signature
+ ) internal view returns (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) {
+ Payload.Decoded memory linkedPayload;
+ linkedPayload.kind = Payload.KIND_CONFIG_UPDATE;
+
+ uint256 rindex;
+ uint256 prevCheckpoint = type(uint256).max;
+
+ while (rindex < _signature.length) {
+ uint256 nrindex;
+
+ {
+ uint256 sigSize;
+ (sigSize, rindex) = _signature.readUint24(rindex);
+ nrindex = sigSize + rindex;
+ }
+
+ address checkpointer = nrindex == _signature.length ? _checkpointer : address(0);
+
+ if (prevCheckpoint == type(uint256).max) {
+ (threshold, weight, imageHash, checkpoint, opHash) =
+ recover(_payload, _signature[rindex:nrindex], true, checkpointer);
+ } else {
+ (threshold, weight, imageHash, checkpoint,) =
+ recover(linkedPayload, _signature[rindex:nrindex], true, checkpointer);
+ }
+
+ if (weight < threshold) {
+ revert LowWeightChainedSignature(_signature[rindex:nrindex], threshold, weight);
+ }
+ rindex = nrindex;
+
+ if (_snapshot.imageHash == imageHash) {
+ _snapshot.imageHash = bytes32(0);
+ }
+
+ if (checkpoint >= prevCheckpoint) {
+ revert WrongChainedCheckpointOrder(checkpoint, prevCheckpoint);
+ }
+
+ linkedPayload.imageHash = imageHash;
+ prevCheckpoint = checkpoint;
+ }
+
+ if (_snapshot.imageHash != bytes32(0) && checkpoint <= _snapshot.checkpoint) {
+ revert UnusedSnapshot(_snapshot);
+ }
+ }
+
+ function recoverBranch(
+ Payload.Decoded memory _payload,
+ bytes32 _opHash,
+ bytes calldata _signature
+ ) internal view returns (uint256 weight, bytes32 root) {
+ unchecked {
+ uint256 rindex;
+
+ // Iterate until the image is completed
+ while (rindex < _signature.length) {
+ // The first byte is half flag (the top nibble)
+ // and the second set of 4 bits can freely be used by the part
+
+ // Read next item type
+ uint256 firstByte;
+ (firstByte, rindex) = _signature.readUint8(rindex);
+
+ // The top 4 bits are the flag
+ uint256 flag = (firstByte & 0xf0) >> 4;
+
+ // Signature hash (0x00)
+ if (flag == FLAG_SIGNATURE_HASH) {
+ // Free bits layout:
+ // - bits [3..0]: Weight (0000 = dynamic, 0001 = 1, ..., 1111 = 15)
+ // We read 64 bytes for an ERC-2098 compact signature (r, yParityAndS).
+ // The top bit of yParityAndS is yParity, the remaining 255 bits are s.
+
+ uint8 addrWeight = uint8(firstByte & 0x0f);
+ if (addrWeight == 0) {
+ (addrWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ bytes32 r;
+ bytes32 s;
+ uint8 v;
+ (r, s, v, rindex) = _signature.readRSVCompact(rindex);
+
+ address addr = ecrecover(_opHash, v, r, s);
+
+ weight += addrWeight;
+ bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Address (0x01) (without signature)
+ if (flag == FLAG_ADDRESS) {
+ // Free bits layout:
+ // - bits [3..0]: Weight (0000 = dynamic, 0001 = 1, 0010 = 2, ...)
+
+ // Read weight
+ uint8 addrWeight = uint8(firstByte & 0x0f);
+ if (addrWeight == 0) {
+ (addrWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ // Read address
+ address addr;
+ (addr, rindex) = _signature.readAddress(rindex);
+
+ // Compute the merkle root WITHOUT adding the weight
+ bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Signature ERC1271 (0x02)
+ if (flag == FLAG_SIGNATURE_ERC1271) {
+ // Free bits layout:
+ // - XX00 : Signature size size (00 = 0 byte, 01 = 1 byte, 10 = 2 bytes, 11 = 3 bytes)
+ // - 00XX : Weight (00 = dynamic, 01 = 1, 10 = 2, 11 = 3)
+
+ // Read weight
+ uint8 addrWeight = uint8(firstByte & 0x03);
+ if (addrWeight == 0) {
+ (addrWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ // Read signer
+ address addr;
+ (addr, rindex) = _signature.readAddress(rindex);
+
+ // Read signature size
+ uint256 sizeSize = uint8(firstByte & 0x0c) >> 2;
+ uint256 size;
+ (size, rindex) = _signature.readUintX(rindex, sizeSize);
+
+ // Read dynamic size signature
+ uint256 nrindex = rindex + size;
+
+ // Call the ERC1271 contract to check if the signature is valid
+ if (IERC1271(addr).isValidSignature(_opHash, _signature[rindex:nrindex]) != IERC1271_MAGIC_VALUE_HASH) {
+ revert InvalidERC1271Signature(_opHash, addr, _signature[rindex:nrindex]);
+ }
+ rindex = nrindex;
+ // Add the weight and compute the merkle root
+ weight += addrWeight;
+ bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Node (0x03)
+ if (flag == FLAG_NODE) {
+ // Free bits left unused
+
+ // Read node hash
+ bytes32 node;
+ (node, rindex) = _signature.readBytes32(rindex);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Branch (0x04)
+ if (flag == FLAG_BRANCH) {
+ // Free bits layout:
+ // - XXXX : Size size (0000 = 0 byte, 0001 = 1 byte, 0010 = 2 bytes, ...)
+
+ // Read size
+ uint256 sizeSize = uint8(firstByte & 0x0f);
+ uint256 size;
+ (size, rindex) = _signature.readUintX(rindex, sizeSize);
+
+ // Enter a branch of the signature merkle tree
+ uint256 nrindex = rindex + size;
+
+ (uint256 nweight, bytes32 node) = recoverBranch(_payload, _opHash, _signature[rindex:nrindex]);
+ rindex = nrindex;
+
+ weight += nweight;
+ root = LibOptim.fkeccak256(root, node);
+ continue;
+ }
+
+ // Nested (0x06)
+ if (flag == FLAG_NESTED) {
+ // Unused free bits:
+ // - XX00 : Weight (00 = dynamic, 01 = 1, 10 = 2, 11 = 3)
+ // - 00XX : Threshold (00 = dynamic, 01 = 1, 10 = 2, 11 = 3)
+
+ // Enter a branch of the signature merkle tree
+ // but with an internal threshold and an external fixed weight
+ uint256 externalWeight = uint8(firstByte & 0x0c) >> 2;
+ if (externalWeight == 0) {
+ (externalWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ uint256 internalThreshold = uint8(firstByte & 0x03);
+ if (internalThreshold == 0) {
+ (internalThreshold, rindex) = _signature.readUint16(rindex);
+ }
+
+ uint256 size;
+ (size, rindex) = _signature.readUint24(rindex);
+ uint256 nrindex = rindex + size;
+
+ (uint256 internalWeight, bytes32 internalRoot) = recoverBranch(_payload, _opHash, _signature[rindex:nrindex]);
+ rindex = nrindex;
+
+ if (internalWeight >= internalThreshold) {
+ weight += externalWeight;
+ }
+
+ bytes32 node = _leafForNested(internalRoot, internalThreshold, externalWeight);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Subdigest (0x05)
+ if (flag == FLAG_SUBDIGEST) {
+ // Free bits left unused
+
+ // A hardcoded always accepted digest
+ // it pushes the weight to the maximum
+ bytes32 hardcoded;
+ (hardcoded, rindex) = _signature.readBytes32(rindex);
+ if (hardcoded == _opHash) {
+ weight = type(uint256).max;
+ }
+
+ bytes32 node = _leafForHardcodedSubdigest(hardcoded);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Signature ETH Sign (0x07)
+ if (flag == FLAG_SIGNATURE_ETH_SIGN) {
+ // Free bits layout:
+ // - bits [3..0]: Weight (0000 = dynamic, 0001 = 1, ..., 1111 = 15)
+ // We read 64 bytes for an ERC-2098 compact signature (r, yParityAndS).
+ // The top bit of yParityAndS is yParity, the remaining 255 bits are s.
+
+ uint8 addrWeight = uint8(firstByte & 0x0f);
+ if (addrWeight == 0) {
+ (addrWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ bytes32 r;
+ bytes32 s;
+ uint8 v;
+ (r, s, v, rindex) = _signature.readRSVCompact(rindex);
+
+ address addr = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _opHash)), v, r, s);
+
+ weight += addrWeight;
+ bytes32 node = _leafForAddressAndWeight(addr, addrWeight);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Signature Any address subdigest (0x08)
+ // similar to subdigest, but allows for counter-factual payloads
+ if (flag == FLAG_SIGNATURE_ANY_ADDRESS_SUBDIGEST) {
+ // Free bits left unused
+
+ // A hardcoded always accepted digest
+ // it pushes the weight to the maximum
+ bytes32 hardcoded;
+ (hardcoded, rindex) = _signature.readBytes32(rindex);
+ bytes32 anyAddressOpHash = _payload.hashFor(address(0));
+ if (hardcoded == anyAddressOpHash) {
+ weight = type(uint256).max;
+ }
+
+ bytes32 node = _leafForAnyAddressSubdigest(hardcoded);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Signature Sapient (0x09)
+ if (flag == FLAG_SIGNATURE_SAPIENT) {
+ // Free bits layout:
+ // - XX00 : Signature size size (00 = 0 byte, 01 = 1 byte, 10 = 2 bytes, 11 = 3 bytes)
+ // - 00XX : Weight (00 = dynamic, 01 = 1, 10 = 2, 11 = 3)
+
+ // Read signer and weight
+ uint8 addrWeight = uint8(firstByte & 0x03);
+ if (addrWeight == 0) {
+ (addrWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ address addr;
+ (addr, rindex) = _signature.readAddress(rindex);
+
+ // Read signature size
+ uint256 size;
+ {
+ uint256 sizeSize = uint8(firstByte & 0x0c) >> 2;
+ (size, rindex) = _signature.readUintX(rindex, sizeSize);
+ }
+
+ // Read dynamic size signature
+ uint256 nrindex = rindex + size;
+
+ // Call the ERC1271 contract to check if the signature is valid
+ bytes32 sapientImageHash = ISapient(addr).recoverSapientSignature(_payload, _signature[rindex:nrindex]);
+ rindex = nrindex;
+
+ // Add the weight and compute the merkle root
+ weight += addrWeight;
+ bytes32 node = _leafForSapient(addr, addrWeight, sapientImageHash);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ // Signature Sapient Compact (0x0A)
+ if (flag == FLAG_SIGNATURE_SAPIENT_COMPACT) {
+ // Free bits layout:
+ // - XX00 : Signature size size (00 = 0 byte, 01 = 1 byte, 10 = 2 bytes, 11 = 3 bytes)
+ // - 00XX : Weight (00 = dynamic, 01 = 1, 10 = 2, 11 = 3)
+
+ // Read signer and weight
+ uint8 addrWeight = uint8(firstByte & 0x03);
+ if (addrWeight == 0) {
+ (addrWeight, rindex) = _signature.readUint8(rindex);
+ }
+
+ address addr;
+ (addr, rindex) = _signature.readAddress(rindex);
+
+ // Read signature size
+ uint256 sizeSize = uint8(firstByte & 0x0c) >> 2;
+ uint256 size;
+ (size, rindex) = _signature.readUintX(rindex, sizeSize);
+
+ // Read dynamic size signature
+ uint256 nrindex = rindex + size;
+
+ // Call the Sapient contract to check if the signature is valid
+ bytes32 sapientImageHash =
+ ISapientCompact(addr).recoverSapientSignatureCompact(_opHash, _signature[rindex:nrindex]);
+ rindex = nrindex;
+ // Add the weight and compute the merkle root
+ weight += addrWeight;
+ bytes32 node = _leafForSapient(addr, addrWeight, sapientImageHash);
+ root = root != bytes32(0) ? LibOptim.fkeccak256(root, node) : node;
+ continue;
+ }
+
+ revert InvalidSignatureFlag(flag);
+ }
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/SelfAuth.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/SelfAuth.sol
new file mode 100644
index 000000000..e583d4dfc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/SelfAuth.sol
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+/// @title SelfAuth
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Modifier for checking if the caller is the same as the contract
+abstract contract SelfAuth {
+
+ /// @notice Error thrown when the caller is not the same as the contract
+ error OnlySelf(address _sender);
+
+ modifier onlySelf() {
+ if (msg.sender != address(this)) {
+ revert OnlySelf(msg.sender);
+ }
+ _;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/Stage1Auth.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/Stage1Auth.sol
new file mode 100644
index 000000000..5f5d457a4
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/Stage1Auth.sol
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Wallet } from "../../Wallet.sol";
+import { Implementation } from "../Implementation.sol";
+import { Storage } from "../Storage.sol";
+import { BaseAuth } from "./BaseAuth.sol";
+
+/// @title Stage1Auth
+/// @author Agustin Aguilar
+/// @notice Stage 1 auth contract
+contract Stage1Auth is BaseAuth, Implementation {
+
+ /// @notice Error thrown when the image hash is zero
+ error ImageHashIsZero();
+ /// @notice Error thrown when the signature type is invalid
+ error InvalidSignatureType(bytes1 _type);
+
+ /// @notice Initialization code hash
+ bytes32 public immutable INIT_CODE_HASH;
+ /// @notice Factory address
+ address public immutable FACTORY;
+ /// @notice Stage 2 implementation address
+ address public immutable STAGE_2_IMPLEMENTATION;
+
+ /// @dev keccak256("org.arcadeum.module.auth.upgradable.image.hash")
+ bytes32 internal constant IMAGE_HASH_KEY = bytes32(0xea7157fa25e3aa17d0ae2d5280fa4e24d421c61842aa85e45194e1145aa72bf8);
+
+ /// @notice Emitted when the image hash is updated
+ event ImageHashUpdated(bytes32 newImageHash);
+
+ constructor(address _factory, address _stage2) {
+ // Build init code hash of the deployed wallets using that module
+ bytes32 initCodeHash = keccak256(abi.encodePacked(Wallet.creationCode, uint256(uint160(address(this)))));
+
+ INIT_CODE_HASH = initCodeHash;
+ FACTORY = _factory;
+ STAGE_2_IMPLEMENTATION = _stage2;
+ }
+
+ function _updateImageHash(
+ bytes32 _imageHash
+ ) internal virtual override {
+ // Update imageHash in storage
+ if (_imageHash == bytes32(0)) {
+ revert ImageHashIsZero();
+ }
+ Storage.writeBytes32(IMAGE_HASH_KEY, _imageHash);
+ emit ImageHashUpdated(_imageHash);
+
+ // Update wallet implementation to stage2 version
+ _updateImplementation(STAGE_2_IMPLEMENTATION);
+ }
+
+ function _isValidImage(
+ bytes32 _imageHash
+ ) internal view virtual override returns (bool) {
+ return address(uint160(uint256(keccak256(abi.encodePacked(hex"ff", FACTORY, _imageHash, INIT_CODE_HASH)))))
+ == address(this);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/Stage2Auth.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/Stage2Auth.sol
new file mode 100644
index 000000000..6242b2871
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/auth/Stage2Auth.sol
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Wallet } from "../../Wallet.sol";
+import { Implementation } from "../Implementation.sol";
+import { Storage } from "../Storage.sol";
+import { BaseAuth } from "./BaseAuth.sol";
+
+/// @title Stage2Auth
+/// @author Agustin Aguilar
+/// @notice Stage 2 auth contract
+contract Stage2Auth is BaseAuth, Implementation {
+
+ /// @dev keccak256("org.arcadeum.module.auth.upgradable.image.hash")
+ bytes32 internal constant IMAGE_HASH_KEY = bytes32(0xea7157fa25e3aa17d0ae2d5280fa4e24d421c61842aa85e45194e1145aa72bf8);
+
+ /// @notice Emitted when the image hash is updated
+ event ImageHashUpdated(bytes32 newImageHash);
+
+ /// @notice Error thrown when the image hash is zero
+ error ImageHashIsZero();
+
+ /// @notice Get the image hash
+ /// @return imageHash The image hash
+ function imageHash() external view virtual returns (bytes32) {
+ return Storage.readBytes32(IMAGE_HASH_KEY);
+ }
+
+ function _isValidImage(
+ bytes32 _imageHash
+ ) internal view virtual override returns (bool) {
+ return _imageHash != bytes32(0) && _imageHash == Storage.readBytes32(IMAGE_HASH_KEY);
+ }
+
+ function _updateImageHash(
+ bytes32 _imageHash
+ ) internal virtual override {
+ if (_imageHash == bytes32(0)) {
+ revert ImageHashIsZero();
+ }
+ Storage.writeBytes32(IMAGE_HASH_KEY, _imageHash);
+ emit ImageHashUpdated(_imageHash);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IAccount.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IAccount.sol
new file mode 100644
index 000000000..8b617b95b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IAccount.sol
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.28;
+
+/**
+ * User Operation struct
+ * @param sender - The sender account of this request.
+ * @param nonce - Unique value the sender uses to verify it is not a replay.
+ * @param initCode - If set, the account contract will be created by this constructor
+ * @param callData - The method call to execute on this account.
+ * @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
+ * @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.
+ * Covers batch overhead.
+ * @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
+ * @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data
+ * The paymaster will pay for the transaction instead of the sender.
+ * @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.
+ */
+struct PackedUserOperation {
+ address sender;
+ uint256 nonce;
+ bytes initCode;
+ bytes callData;
+ bytes32 accountGasLimits;
+ uint256 preVerificationGas;
+ bytes32 gasFees;
+ bytes paymasterAndData;
+ bytes signature;
+}
+
+interface IAccount {
+
+ /**
+ * Validate user's signature and nonce
+ * the entryPoint will make the call to the recipient only if this validation call returns successfully.
+ * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
+ * This allows making a "simulation call" without a valid signature
+ * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
+ *
+ * @dev Must validate caller is the entryPoint.
+ * Must validate the signature and nonce
+ * @param userOp - The operation that is about to be executed.
+ * @param userOpHash - Hash of the user's request data. can be used as the basis for signature.
+ * @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.
+ * This is the minimum amount to transfer to the sender(entryPoint) to be
+ * able to make the call. The excess is left as a deposit in the entrypoint
+ * for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()".
+ * In case there is a paymaster in the request (or the current deposit is high
+ * enough), this value will be zero.
+ * @return validationData - Packaged ValidationData structure. use `_packValidationData` and
+ * `_unpackValidationData` to encode and decode.
+ * <20-byte> aggregatorOrSigFail - 0 for valid signature, 1 to mark signature failure,
+ * otherwise, an address of an "aggregator" contract.
+ * <6-byte> validUntil - Last timestamp this operation is valid at, or 0 for "indefinitely"
+ * <6-byte> validAfter - First timestamp this operation is valid
+ * If an account doesn't use time-range, it is enough to
+ * return SIG_VALIDATION_FAILED value (1) for signature failure.
+ * Note that the validation code cannot use block.timestamp (or block.number) directly.
+ */
+ function validateUserOp(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingAccountFunds
+ ) external returns (uint256 validationData);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IAuth.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IAuth.sol
new file mode 100644
index 000000000..6d8df782d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IAuth.sol
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+/// @title IAuth
+/// @author Agustin Aguilar, Michael Standen, William Hua
+/// @notice Internal interface for the auth modules
+abstract contract IAuth {
+
+ function _isValidImage(
+ bytes32 imageHash
+ ) internal view virtual returns (bool isValid);
+
+ function _updateImageHash(
+ bytes32 imageHash
+ ) internal virtual;
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/ICheckpointer.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/ICheckpointer.sol
new file mode 100644
index 000000000..99064d20d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/ICheckpointer.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../Payload.sol";
+
+/// @notice Snapshot for a specific wallet
+/// @param imageHash Image hash of the wallet
+/// @param checkpoint Checkpoint identifier
+struct Snapshot {
+ bytes32 imageHash;
+ uint256 checkpoint;
+}
+
+/// @title ICheckpointer
+/// @author Agustin Aguilar
+/// @notice Interface for the checkpointer module
+interface ICheckpointer {
+
+ /// @notice Get the snapshot for a specific wallet
+ /// @param _wallet The wallet address
+ /// @param _proof The proof
+ /// @return snapshot The snapshot
+ function snapshotFor(address _wallet, bytes calldata _proof) external view returns (Snapshot memory snapshot);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IDelegatedExtension.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IDelegatedExtension.sol
new file mode 100644
index 000000000..7d958ce55
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IDelegatedExtension.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+/// @title IDelegatedExtension
+/// @author Agustin Aguilar
+/// @notice Interface for the delegated extension module
+interface IDelegatedExtension {
+
+ /// @notice Handle a sequence delegate call
+ /// @param _opHash The operation hash
+ /// @param _startingGas The starting gas
+ /// @param _index The index
+ /// @param _numCalls The number of calls
+ /// @param _space The space
+ /// @param _data The data
+ function handleSequenceDelegateCall(
+ bytes32 _opHash,
+ uint256 _startingGas,
+ uint256 _index,
+ uint256 _numCalls,
+ uint256 _space,
+ bytes calldata _data
+ ) external;
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC1155Receiver.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC1155Receiver.sol
new file mode 100644
index 000000000..3a95246bd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC1155Receiver.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+/// @title IERC1155Receiver
+/// @notice Interface for the ERC1155 receiver module
+interface IERC1155Receiver {
+
+ /// @notice Called when a single ERC1155 token is transferred to this contract
+ /// @param operator The address which initiated the transfer
+ /// @param from The address which previously owned the token
+ /// @param tokenId The ID of the token being transferred
+ /// @param value The amount of token being transferred
+ /// @param data Additional data with no specified format
+ /// @return magicValue On a success, the selector of the function that was called
+ function onERC1155Received(
+ address operator,
+ address from,
+ uint256 tokenId,
+ uint256 value,
+ bytes calldata data
+ ) external returns (bytes4 magicValue);
+
+ /// @notice Called when multiple ERC1155 tokens are transferred to this contract
+ /// @param operator The address which initiated the transfer
+ /// @param from The address which previously owned the token
+ /// @param ids The list of token IDs being transferred
+ /// @param values The amounts of each token being transferred
+ /// @param data Additional data with no specified format
+ /// @return magicValue On a success, the selector of the function that was called
+ function onERC1155BatchReceived(
+ address operator,
+ address from,
+ uint256[] calldata ids,
+ uint256[] calldata values,
+ bytes calldata data
+ ) external returns (bytes4 magicValue);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC1271.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC1271.sol
new file mode 100644
index 000000000..854f8c5fa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC1271.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+bytes4 constant IERC1271_MAGIC_VALUE_HASH = 0x1626ba7e;
+bytes4 constant IERC1271_MAGIC_VALUE_BYTES = 0x20c13b0b;
+
+/// @title IERC1271
+/// @notice Interface for ERC1271
+interface IERC1271 {
+
+ /// @notice Verifies whether the provided signature is valid with respect to the provided hash
+ /// @dev MUST return the correct magic value if the signature provided is valid for the provided hash
+ /// > The bytes4 magic value to return when signature is valid is 0x1626ba7e : bytes4(keccak256("isValidSignature(bytes32,bytes)")
+ /// > This function MAY modify Ethereum's state
+ /// @param _hash keccak256 hash that was signed
+ /// @param _signature Signature byte array associated with _data
+ /// @return magicValue Magic value 0x1626ba7e if the signature is valid and 0x0 otherwise
+ function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4 magicValue);
+
+}
+
+/// @title IERC1271Data
+/// @notice Deprecated interface for ERC1271 using bytes instead of bytes32
+interface IERC1271Data {
+
+ /// @notice Verifies whether the provided signature is valid with respect to the provided hash
+ /// @dev MUST return the correct magic value if the signature provided is valid for the provided hash
+ /// > The bytes4 magic value to return when signature is valid is 0x20c13b0b : bytes4(keccak256("isValidSignature(bytes,bytes)")
+ /// > This function MAY modify Ethereum's state
+ /// @param _data Data that was signed
+ /// @param _signature Signature byte array associated with _data
+ /// @return magicValue Magic value 0x20c13b0b if the signature is valid and 0x0 otherwise
+ function isValidSignature(bytes calldata _data, bytes calldata _signature) external view returns (bytes4 magicValue);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC223Receiver.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC223Receiver.sol
new file mode 100644
index 000000000..4db7a04c5
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC223Receiver.sol
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+/// @title IERC223Receiver
+/// @notice Interface for the ERC223 receiver module
+interface IERC223Receiver {
+
+ /// @notice Called when ERC223 tokens are received by this contract
+ /// @param from The address which previously owned the tokens
+ /// @param value The amount of tokens being transferred
+ /// @param data Transaction metadata
+ /// @return signature The signature of the function to be called
+ function tokenReceived(address from, uint256 value, bytes calldata data) external returns (bytes4 signature);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC721Receiver.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC721Receiver.sol
new file mode 100644
index 000000000..77b3bcfd7
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC721Receiver.sol
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+/// @title IERC721Receiver
+/// @notice Interface for the ERC721 receiver module
+interface IERC721Receiver {
+
+ /// @notice Called when a single ERC721 token is transferred to this contract
+ /// @param operator The address which initiated the transfer
+ /// @param from The address which previously owned the token
+ /// @param tokenId The ID of the token being transferred
+ /// @param data Additional data with no specified format
+ /// @return magicValue On a success, the selector of the function that was called
+ function onERC721Received(
+ address operator,
+ address from,
+ uint256 tokenId,
+ bytes calldata data
+ ) external returns (bytes4 magicValue);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC777Receiver.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC777Receiver.sol
new file mode 100644
index 000000000..d32ea85a1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IERC777Receiver.sol
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+/// @title IERC777Receiver
+/// @notice Interface for the ERC777 receiver module
+interface IERC777Receiver {
+
+ /// @notice Called when tokens are received by this contract
+ /// @param operator The address which initiated the transfer
+ /// @param from The address which previously owned the tokens
+ /// @param to The address which is receiving the tokens
+ /// @param amount The amount of tokens being transferred
+ /// @param data Additional data with no specified format
+ /// @param operatorData Additional data with no specified format
+ function tokensReceived(
+ address operator,
+ address from,
+ address to,
+ uint256 amount,
+ bytes calldata data,
+ bytes calldata operatorData
+ ) external;
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IEntryPoint.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IEntryPoint.sol
new file mode 100644
index 000000000..31c1f1492
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IEntryPoint.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.28;
+
+interface IEntryPoint {
+
+ function depositTo(
+ address account
+ ) external payable;
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IPartialAuth.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IPartialAuth.sol
new file mode 100644
index 000000000..d66f747ea
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/IPartialAuth.sol
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../Payload.sol";
+
+/// @title IPartialAuth
+/// @author Agustin Aguilar
+/// @notice Interface for the partial auth module
+interface IPartialAuth {
+
+ /// @notice Recover the partial signature
+ /// @param _payload The payload
+ /// @param _signature The signature to recover
+ /// @return threshold The signature threshold
+ /// @return weight The derived weight
+ /// @return isValidImage Whether the image hash is valid
+ /// @return imageHash The derived image hash
+ /// @return checkpoint The checkpoint identifier
+ /// @return opHash The hash of the payload
+ function recoverPartialSignature(
+ Payload.Decoded calldata _payload,
+ bytes calldata _signature
+ )
+ external
+ view
+ returns (
+ uint256 threshold,
+ uint256 weight,
+ bool isValidImage,
+ bytes32 imageHash,
+ uint256 checkpoint,
+ bytes32 opHash
+ );
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/ISapient.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/ISapient.sol
new file mode 100644
index 000000000..e600ffd9e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/modules/interfaces/ISapient.sol
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../Payload.sol";
+
+/// @title ISapient
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Sapient signers take an explicit payload and return their own "imageHash" as result
+/// @dev The consumer of this signer must validate if the imageHash is valid or not, for the desired configuration
+interface ISapient {
+
+ /// @notice Recovers the image hash of a given signature
+ /// @param payload The payload to recover the signature from
+ /// @param signature The signature to recover the image hash from
+ /// @return imageHash The recovered image hash
+ function recoverSapientSignature(
+ Payload.Decoded calldata payload,
+ bytes calldata signature
+ ) external view returns (bytes32 imageHash);
+
+}
+
+/// @title ISapientCompact
+/// @author Agustin Aguilar, Michael Standen
+/// @notice Sapient signers take a compacted payload and return their own "imageHash" as result
+/// @dev The consumer of this signer must validate if the imageHash is valid or not, for the desired configuration
+interface ISapientCompact {
+
+ /// @notice Recovers the image hash of a given signature, using a hashed payload
+ /// @param digest The digest of the payload
+ /// @param signature The signature to recover the image hash from
+ /// @return imageHash The recovered image hash
+ function recoverSapientSignatureCompact(
+ bytes32 digest,
+ bytes calldata signature
+ ) external view returns (bytes32 imageHash);
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/utils/Base64.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/Base64.sol
new file mode 100644
index 000000000..af97c9d2a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/Base64.sol
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.4;
+
+/// @notice Library to encode strings in Base64.
+/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol)
+/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol)
+/// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - .
+library Base64 {
+
+ /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
+ /// See: https://datatracker.ietf.org/doc/html/rfc4648
+ /// @param fileSafe Whether to replace '+' with '-' and '/' with '_'.
+ /// @param noPadding Whether to strip away the padding.
+ function encode(bytes memory data, bool fileSafe, bool noPadding) internal pure returns (string memory result) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ let dataLength := mload(data)
+
+ if dataLength {
+ // Multiply by 4/3 rounded up.
+ // The `shl(2, ...)` is equivalent to multiplying by 4.
+ let encodedLength := shl(2, div(add(dataLength, 2), 3))
+
+ // Set `result` to point to the start of the free memory.
+ result := mload(0x40)
+
+ // Store the table into the scratch space.
+ // Offsetted by -1 byte so that the `mload` will load the character.
+ // We will rewrite the free memory pointer at `0x40` later with
+ // the allocated size.
+ // The magic constant 0x0670 will turn "-_" into "+/".
+ mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
+ mstore(0x3f, xor("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0670)))
+
+ // Skip the first slot, which stores the length.
+ let ptr := add(result, 0x20)
+ let end := add(ptr, encodedLength)
+
+ let dataEnd := add(add(0x20, data), dataLength)
+ let dataEndValue := mload(dataEnd) // Cache the value at the `dataEnd` slot.
+ mstore(dataEnd, 0x00) // Zeroize the `dataEnd` slot to clear dirty bits.
+
+ // Run over the input, 3 bytes at a time.
+ for { } 1 { } {
+ data := add(data, 3) // Advance 3 bytes.
+ let input := mload(data)
+
+ // Write 4 bytes. Optimized for fewer stack operations.
+ mstore8(0, mload(and(shr(18, input), 0x3F)))
+ mstore8(1, mload(and(shr(12, input), 0x3F)))
+ mstore8(2, mload(and(shr(6, input), 0x3F)))
+ mstore8(3, mload(and(input, 0x3F)))
+ mstore(ptr, mload(0x00))
+
+ ptr := add(ptr, 4) // Advance 4 bytes.
+ if iszero(lt(ptr, end)) { break }
+ }
+ mstore(dataEnd, dataEndValue) // Restore the cached value at `dataEnd`.
+ mstore(0x40, add(end, 0x20)) // Allocate the memory.
+ // Equivalent to `o = [0, 2, 1][dataLength % 3]`.
+ let o := div(2, mod(dataLength, 3))
+ // Offset `ptr` and pad with '='. We can simply write over the end.
+ mstore(sub(ptr, o), shl(240, 0x3d3d))
+ // Set `o` to zero if there is padding.
+ o := mul(iszero(iszero(noPadding)), o)
+ mstore(sub(ptr, o), 0) // Zeroize the slot after the string.
+ mstore(result, sub(encodedLength, o)) // Store the length.
+ }
+ }
+ }
+
+ /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
+ /// Equivalent to `encode(data, false, false)`.
+ function encode(
+ bytes memory data
+ ) internal pure returns (string memory result) {
+ result = encode(data, false, false);
+ }
+
+ /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
+ /// Equivalent to `encode(data, fileSafe, false)`.
+ function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) {
+ result = encode(data, fileSafe, false);
+ }
+
+ /// @dev Decodes base64 encoded `data`.
+ ///
+ /// Supports:
+ /// - RFC 4648 (both standard and file-safe mode).
+ /// - RFC 3501 (63: ',').
+ ///
+ /// Does not support:
+ /// - Line breaks.
+ ///
+ /// Note: For performance reasons,
+ /// this function will NOT revert on invalid `data` inputs.
+ /// Outputs for invalid inputs will simply be undefined behaviour.
+ /// It is the user's responsibility to ensure that the `data`
+ /// is a valid base64 encoded string.
+ function decode(
+ string memory data
+ ) internal pure returns (bytes memory result) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ let dataLength := mload(data)
+
+ if dataLength {
+ let decodedLength := mul(shr(2, dataLength), 3)
+
+ for { } 1 { } {
+ // If padded.
+ if iszero(and(dataLength, 3)) {
+ let t := xor(mload(add(data, dataLength)), 0x3d3d)
+ // forgefmt: disable-next-item
+ decodedLength := sub(
+ decodedLength,
+ add(iszero(byte(30, t)), iszero(byte(31, t)))
+ )
+ break
+ }
+ // If non-padded.
+ decodedLength := add(decodedLength, sub(and(dataLength, 3), 1))
+ break
+ }
+ result := mload(0x40)
+
+ // Write the length of the bytes.
+ mstore(result, decodedLength)
+
+ // Skip the first slot, which stores the length.
+ let ptr := add(result, 0x20)
+ let end := add(ptr, decodedLength)
+
+ // Load the table into the scratch space.
+ // Constants are optimized for smaller bytecode with zero gas overhead.
+ // `m` also doubles as the mask of the upper 6 bits.
+ let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc
+ mstore(0x5b, m)
+ mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064)
+ mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4)
+
+ for { } 1 { } {
+ // Read 4 bytes.
+ data := add(data, 4)
+ let input := mload(data)
+
+ // Write 3 bytes.
+ // forgefmt: disable-next-item
+ mstore(ptr, or(
+ and(m, mload(byte(28, input))),
+ shr(6, or(
+ and(m, mload(byte(29, input))),
+ shr(6, or(
+ and(m, mload(byte(30, input))),
+ shr(6, mload(byte(31, input)))
+ ))
+ ))
+ ))
+ ptr := add(ptr, 3)
+ if iszero(lt(ptr, end)) { break }
+ }
+ mstore(0x40, add(end, 0x20)) // Allocate the memory.
+ mstore(end, 0) // Zeroize the slot after the bytes.
+ mstore(0x60, 0) // Restore the zero slot.
+ }
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/utils/LibBytes.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/LibBytes.sol
new file mode 100644
index 000000000..0dd0bacbb
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/LibBytes.sol
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+/// @title Library for reading data from bytes arrays
+/// @author Agustin Aguilar (aa@horizon.io), Michael Standen (mstan@horizon.io)
+/// @notice This library contains functions for reading data from bytes arrays.
+/// @dev These functions do not check if the input index is within the bounds of the data array.
+/// @dev Reading out of bounds may return dirty values.
+library LibBytes {
+
+ function readFirstUint8(
+ bytes calldata _data
+ ) internal pure returns (uint8 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(_data.offset)
+ a := shr(248, word)
+ newPointer := 1
+ }
+ }
+
+ function readUint8(bytes calldata _data, uint256 _index) internal pure returns (uint8 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ a := shr(248, word)
+ newPointer := add(_index, 1)
+ }
+ }
+
+ function readUint16(bytes calldata _data, uint256 _index) internal pure returns (uint16 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ a := shr(240, word)
+ newPointer := add(_index, 2)
+ }
+ }
+
+ function readUint24(bytes calldata _data, uint256 _index) internal pure returns (uint24 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ a := shr(232, word)
+ newPointer := add(_index, 3)
+ }
+ }
+
+ function readUint64(bytes calldata _data, uint256 _index) internal pure returns (uint64 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ a := shr(192, word)
+ newPointer := add(_index, 8)
+ }
+ }
+
+ function readUint160(bytes calldata _data, uint256 _index) internal pure returns (uint160 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ a := shr(96, word)
+ newPointer := add(_index, 20)
+ }
+ }
+
+ function readUint256(bytes calldata _data, uint256 _index) internal pure returns (uint256 a, uint256 newPointer) {
+ assembly {
+ a := calldataload(add(_index, _data.offset))
+ newPointer := add(_index, 32)
+ }
+ }
+
+ function readUintX(
+ bytes calldata _data,
+ uint256 _index,
+ uint256 _length
+ ) internal pure returns (uint256 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ let shift := sub(256, mul(_length, 8))
+ a := and(shr(shift, word), sub(shl(mul(8, _length), 1), 1))
+ newPointer := add(_index, _length)
+ }
+ }
+
+ function readBytes4(bytes calldata _data, uint256 _pointer) internal pure returns (bytes4 a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_pointer, _data.offset))
+ a := and(word, 0xffffffff00000000000000000000000000000000000000000000000000000000)
+ newPointer := add(_pointer, 4)
+ }
+ }
+
+ function readBytes32(bytes calldata _data, uint256 _pointer) internal pure returns (bytes32 a, uint256 newPointer) {
+ assembly {
+ a := calldataload(add(_pointer, _data.offset))
+ newPointer := add(_pointer, 32)
+ }
+ }
+
+ function readAddress(bytes calldata _data, uint256 _index) internal pure returns (address a, uint256 newPointer) {
+ assembly {
+ let word := calldataload(add(_index, _data.offset))
+ a := and(shr(96, word), 0xffffffffffffffffffffffffffffffffffffffff)
+ newPointer := add(_index, 20)
+ }
+ }
+
+ /// @dev ERC-2098 Compact Signature
+ function readRSVCompact(
+ bytes calldata _data,
+ uint256 _index
+ ) internal pure returns (bytes32 r, bytes32 s, uint8 v, uint256 newPointer) {
+ uint256 yParityAndS;
+ assembly {
+ r := calldataload(add(_index, _data.offset))
+ yParityAndS := calldataload(add(_index, add(_data.offset, 32)))
+ newPointer := add(_index, 64)
+ }
+ uint256 yParity = uint256(yParityAndS >> 255);
+ s = bytes32(uint256(yParityAndS) & ((1 << 255) - 1));
+ v = uint8(yParity) + 27;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/utils/LibOptim.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/LibOptim.sol
new file mode 100644
index 000000000..e43a2cd87
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/LibOptim.sol
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.18;
+
+/// @title LibOptim
+/// @author Agustin Aguilar
+/// @notice Library for optimized EVM operations
+library LibOptim {
+
+ /**
+ * @notice Computes the keccak256 hash of two 32-byte inputs.
+ * @dev It uses only scratch memory space.
+ * @param _a The first 32 bytes of the hash.
+ * @param _b The second 32 bytes of the hash.
+ * @return c The keccak256 hash of the two 32-byte inputs.
+ */
+ function fkeccak256(bytes32 _a, bytes32 _b) internal pure returns (bytes32 c) {
+ assembly {
+ mstore(0, _a)
+ mstore(32, _b)
+ c := keccak256(0, 64)
+ }
+ }
+
+ /**
+ * @notice Returns the return data from the last call.
+ * @return r The return data from the last call.
+ */
+ function returnData() internal pure returns (bytes memory r) {
+ assembly {
+ let size := returndatasize()
+ r := mload(0x40)
+ let start := add(r, 32)
+ mstore(0x40, add(start, size))
+ mstore(r, size)
+ returndatacopy(start, 0, size)
+ }
+ }
+
+ /**
+ * @notice Calls another contract with the given parameters.
+ * @dev This method doesn't increase the memory pointer.
+ * @param _to The address of the contract to call.
+ * @param _val The value to send to the contract.
+ * @param _gas The amount of gas to provide for the call.
+ * @param _data The data to send to the contract.
+ * @return r The success status of the call.
+ */
+ function call(address _to, uint256 _val, uint256 _gas, bytes memory _data) internal returns (bool r) {
+ assembly {
+ r := call(_gas, _to, _val, add(_data, 32), mload(_data), 0, 0)
+ }
+ }
+
+ /**
+ * @notice Calls another contract with the given parameters, using delegatecall.
+ * @dev This method doesn't increase the memory pointer.
+ * @param _to The address of the contract to call.
+ * @param _gas The amount of gas to provide for the call.
+ * @param _data The data to send to the contract.
+ * @return r The success status of the call.
+ */
+ function delegatecall(address _to, uint256 _gas, bytes memory _data) internal returns (bool r) {
+ assembly {
+ r := delegatecall(_gas, _to, add(_data, 32), mload(_data), 0, 0)
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/utils/P256.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/P256.sol
new file mode 100644
index 000000000..3446aa54b
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/P256.sol
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.4;
+
+/// @notice Gas optimized P256 wrapper.
+/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/P256.sol)
+/// @author Modified from Daimo P256 Verifier (https://github.com/daimo-eth/p256-verifier/blob/master/src/P256.sol)
+/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/P256.sol)
+library P256 {
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* CUSTOM ERRORS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Unable to verify the P256 signature, due to missing
+ /// RIP-7212 P256 verifier precompile and missing Solidity P256 verifier.
+ error P256VerificationFailed();
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* CONSTANTS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Address of the Solidity P256 verifier.
+ /// Please make sure the contract is deployed onto the chain you are working on.
+ /// See: https://gist.github.com/Vectorized/599b0d8a94d21bc74700eb1354e2f55c
+ /// Unlike RIP-7212, this verifier returns `uint256(0)` on failure, to
+ /// facilitate easier existence check. This verifier will also never revert.
+ address internal constant VERIFIER = 0x000000000000D01eA45F9eFD5c54f037Fa57Ea1a;
+
+ /// @dev Address of the RIP-7212 P256 verifier precompile.
+ /// Currently, we don't support EIP-7212's precompile at 0x0b as it has not been finalized.
+ /// See: https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md
+ address internal constant RIP_PRECOMPILE = 0x0000000000000000000000000000000000000100;
+
+ /// @dev The order of the secp256r1 elliptic curve.
+ uint256 internal constant N = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;
+
+ /// @dev `N/2`. Used for checking the malleability of the signature.
+ uint256 private constant _HALF_N = 0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8;
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* P256 VERIFICATION OPERATIONS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Returns if the signature (`r`, `s`) is valid for `hash` and public key (`x`, `y`).
+ /// Does NOT include the malleability check.
+ function verifySignatureAllowMalleability(
+ bytes32 hash,
+ bytes32 r,
+ bytes32 s,
+ bytes32 x,
+ bytes32 y
+ ) internal view returns (bool isValid) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ let m := mload(0x40)
+ mstore(m, hash)
+ mstore(add(m, 0x20), r)
+ mstore(add(m, 0x40), s)
+ mstore(add(m, 0x60), x)
+ mstore(add(m, 0x80), y)
+ mstore(0x00, 0) // Zeroize the return slot before the staticcalls.
+ pop(staticcall(gas(), RIP_PRECOMPILE, m, 0xa0, 0x00, 0x20))
+ // RIP-7212 dictates that success returns `uint256(1)`.
+ // But failure returns zero returndata, which is ambiguous.
+ if iszero(returndatasize()) {
+ pop(staticcall(gas(), VERIFIER, m, 0xa0, returndatasize(), 0x20))
+ // Unlike RIP-7212, the verifier returns `uint256(0)` on failure,
+ // allowing us to use the returndatasize to determine existence.
+ if iszero(returndatasize()) {
+ mstore(returndatasize(), 0xd0d5039b) // `P256VerificationFailed()`.
+ revert(0x1c, 0x04)
+ }
+ }
+ isValid := eq(1, mload(0x00))
+ }
+ }
+
+ /// @dev Returns if the signature (`r`, `s`) is valid for `hash` and public key (`x`, `y`).
+ /// Includes the malleability check.
+ function verifySignature(
+ bytes32 hash,
+ bytes32 r,
+ bytes32 s,
+ bytes32 x,
+ bytes32 y
+ ) internal view returns (bool isValid) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ let m := mload(0x40)
+ mstore(m, hash)
+ mstore(add(m, 0x20), r)
+ mstore(add(m, 0x40), s)
+ mstore(add(m, 0x60), x)
+ mstore(add(m, 0x80), y)
+ mstore(0x00, 0) // Zeroize the return slot before the staticcalls.
+ pop(staticcall(gas(), RIP_PRECOMPILE, m, 0xa0, 0x00, 0x20))
+ // RIP-7212 dictates that success returns `uint256(1)`.
+ // But failure returns zero returndata, which is ambiguous.
+ if iszero(returndatasize()) {
+ pop(staticcall(gas(), VERIFIER, m, 0xa0, returndatasize(), 0x20))
+ // Unlike RIP-7212, the verifier returns `uint256(0)` on failure,
+ // allowing us to use the returndatasize to determine existence.
+ if iszero(returndatasize()) {
+ mstore(returndatasize(), 0xd0d5039b) // `P256VerificationFailed()`.
+ revert(0x1c, 0x04)
+ }
+ }
+ // Optimize for happy path. Users are unlikely to pass in malleable signatures.
+ isValid := lt(gt(s, _HALF_N), eq(1, mload(0x00)))
+ }
+ }
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* OTHER OPERATIONS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Returns `s` normalized to the lower half of the curve.
+ function normalized(
+ bytes32 s
+ ) internal pure returns (bytes32 result) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ result := xor(s, mul(xor(sub(N, s), s), gt(s, _HALF_N)))
+ }
+ }
+
+ /// @dev Helper function for `abi.decode(encoded, (bytes32, bytes32))`.
+ /// If `encoded.length < 64`, `(x, y)` will be `(0, 0)`, which is an invalid point.
+ function tryDecodePoint(
+ bytes memory encoded
+ ) internal pure returns (bytes32 x, bytes32 y) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ let t := gt(mload(encoded), 0x3f)
+ x := mul(mload(add(encoded, 0x20)), t)
+ y := mul(mload(add(encoded, 0x40)), t)
+ }
+ }
+
+ /// @dev Helper function for `abi.decode(encoded, (bytes32, bytes32))`.
+ /// If `encoded.length < 64`, `(x, y)` will be `(0, 0)`, which is an invalid point.
+ function tryDecodePointCalldata(
+ bytes calldata encoded
+ ) internal pure returns (bytes32 x, bytes32 y) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ let t := gt(encoded.length, 0x3f)
+ x := mul(calldataload(encoded.offset), t)
+ y := mul(calldataload(add(encoded.offset, 0x20)), t)
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/src/utils/WebAuthn.sol b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/WebAuthn.sol
new file mode 100644
index 000000000..754809dfd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/src/utils/WebAuthn.sol
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.4;
+
+import { Base64 } from "./Base64.sol";
+import { P256 } from "./P256.sol";
+
+/// @notice WebAuthn helper.
+/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/WebAuthn.sol)
+/// @author Modified from Daimo WebAuthn (https://github.com/daimo-eth/p256-verifier/blob/master/src/WebAuthn.sol)
+/// @author Modified from Coinbase WebAuthn (https://github.com/base-org/webauthn-sol/blob/main/src/WebAuthn.sol)
+library WebAuthn {
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* STRUCTS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Helps make encoding and decoding easier, alleviates stack-too-deep.
+ struct WebAuthnAuth {
+ // The WebAuthn authenticator data.
+ // See: https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-authenticatordata.
+ bytes authenticatorData;
+ // The WebAuthn client data JSON.
+ // See: https://www.w3.org/TR/webauthn-2/#dom-authenticatorresponse-clientdatajson.
+ string clientDataJSON;
+ // Start index of "challenge":"..." in `clientDataJSON`.
+ uint256 challengeIndex;
+ // Start index of "type":"..." in `clientDataJSON`.
+ uint256 typeIndex;
+ // The r value of secp256r1 signature.
+ bytes32 r;
+ // The s value of secp256r1 signature.
+ bytes32 s;
+ }
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* WEBAUTHN VERIFICATION OPERATIONS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Verifies a Webauthn Authentication Assertion.
+ /// See: https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion.
+ ///
+ /// We do not verify all the steps as described in the specification, only ones
+ /// relevant to our context. Please carefully read through this list before usage.
+ ///
+ /// Specifically, we do verify the following:
+ /// - Verify that `authenticatorData` (which comes from the authenticator,
+ /// such as iCloud Keychain) indicates a well-formed assertion with the
+ /// "User Present" bit set. If `requireUserVerification` is set, checks that the
+ /// authenticator enforced user verification. User verification should be required
+ /// if, and only if, `options.userVerification` is set to required in the request.
+ /// - Verifies that the client JSON is of type "webauthn.get",
+ /// i.e. the client was responding to a request to assert authentication.
+ /// - Verifies that the client JSON contains the requested challenge.
+ /// - Verifies that (r, s) constitute a valid signature over both the
+ /// `authData` and client JSON, for public key (x, y).
+ ///
+ /// We make some assumptions about the particular use case of this verifier,
+ /// so we do NOT verify the following:
+ /// - Does NOT verify that the origin in the `clientDataJSON` matches the
+ /// Relying Party's origin: it is considered the authenticator's responsibility to
+ /// ensure that the user is interacting with the correct RP. This is enforced by
+ /// most high quality authenticators properly, particularly the iCloud Keychain
+ /// and Google Password Manager were tested.
+ /// - Does NOT verify That `topOrigin` in `clientDataJSON` is well-formed:
+ /// We assume it would never be present, i.e. the credentials are never used in a
+ /// cross-origin/iframe context. The website/app set up should disallow cross-origin
+ /// usage of the credentials. This is the default behavior for created credentials
+ /// in common settings.
+ /// - Does NOT verify that the `rpIdHash` in `authenticatorData` is the SHA-256 hash
+ /// of the RP ID expected by the Relying Party:
+ /// this means that we rely on the authenticator to properly enforce
+ /// credentials to be used only by the correct RP.
+ /// This is generally enforced with features like Apple App Site Association
+ /// and Google Asset Links. To protect from edge cases in which a previously-linked
+ /// RP ID is removed from the authorized RP IDs, we recommend that messages
+ /// signed by the authenticator include some expiry mechanism.
+ /// - Does NOT verify the credential backup state: this assumes the credential backup
+ /// state is NOT used as part of Relying Party business logic or policy.
+ /// - Does NOT verify the values of the client extension outputs:
+ /// this assumes that the Relying Party does not use client extension outputs.
+ /// - Does NOT verify the signature counter: signature counters are intended to enable
+ /// risk scoring for the Relying Party. This assumes risk scoring is not used as part
+ /// of Relying Party business logic or policy.
+ /// - Does NOT verify the attestation object: this assumes that
+ /// response.attestationObject is NOT present in the response,
+ /// i.e. the RP does not intend to verify an attestation.
+ function verify(
+ bytes memory challenge,
+ bool requireUserVerification,
+ WebAuthnAuth memory auth,
+ bytes32 x,
+ bytes32 y
+ ) internal view returns (bool result) {
+ bytes32 messageHash;
+ string memory encoded = Base64.encode(challenge, true, true);
+ /// @solidity memory-safe-assembly
+ assembly {
+ let clientDataJSON := mload(add(auth, 0x20))
+ let n := mload(clientDataJSON) // `clientDataJSON`'s length.
+ let o := add(clientDataJSON, 0x20) // Start of `clientData`'s bytes.
+ {
+ let c := mload(add(auth, 0x40)) // Challenge index in `clientDataJSON`.
+ let t := mload(add(auth, 0x60)) // Type index in `clientDataJSON`.
+ let l := mload(encoded) // Cache `encoded`'s length.
+ let q := add(l, 0x0d) // Length of `encoded` prefixed with '"challenge":"'.
+ mstore(encoded, shr(152, '"challenge":"')) // Temp prefix with '"challenge":"'.
+ result :=
+ and(
+ // 11. Verify JSON's type. Also checks for possible addition overflows.
+ and(
+ eq(shr(88, mload(add(o, t))), shr(88, '"type":"webauthn.get"')), lt(shr(128, or(t, c)), lt(add(0x14, t), n))
+ ),
+ // 12. Verify JSON's challenge. Includes a check for the closing '"'.
+ and(
+ eq(keccak256(add(o, c), q), keccak256(add(encoded, 0x13), q)),
+ and(eq(byte(0, mload(add(add(o, c), q))), 34), lt(add(q, c), n))
+ )
+ )
+ mstore(encoded, l) // Restore `encoded`'s length, in case of string interning.
+ }
+ // Skip 13., 14., 15.
+ let l := mload(mload(auth)) // Length of `authenticatorData`.
+ // 16. Verify that the "User Present" flag is set (bit 0).
+ // 17. Verify that the "User Verified" flag is set (bit 2), if required.
+ // See: https://www.w3.org/TR/webauthn-2/#flags.
+ let u := or(1, shl(2, iszero(iszero(requireUserVerification))))
+ result := and(and(result, gt(l, 0x20)), eq(and(mload(add(mload(auth), 0x21)), u), u))
+ if result {
+ let p := add(mload(auth), 0x20) // Start of `authenticatorData`'s bytes.
+ let e := add(p, l) // Location of the word after `authenticatorData`.
+ let w := mload(e) // Cache the word after `authenticatorData`.
+ // 19. Compute `sha256(clientDataJSON)`.
+ // 20. Compute `sha256(authenticatorData ‖ sha256(clientDataJSON))`.
+ // forgefmt: disable-next-item
+ messageHash := mload(staticcall(gas(),
+ shl(1, staticcall(gas(), 2, o, n, e, 0x20)), p, add(l, 0x20), 0x01, 0x20))
+ mstore(e, w) // Restore the word after `authenticatorData`, in case of reuse.
+ // `returndatasize()` is `0x20` on `sha256` success, and `0x00` otherwise.
+ if iszero(returndatasize()) { invalid() }
+ }
+ }
+ // `P256.verifySignature` returns false if `s > N/2` due to the malleability check.
+ if (result) {
+ result = P256.verifySignature(messageHash, auth.r, auth.s, x, y);
+ }
+ }
+
+ /// @dev Plain variant of verify.
+ function verify(
+ bytes memory challenge,
+ bool requireUserVerification,
+ bytes memory authenticatorData,
+ string memory clientDataJSON,
+ uint256 challengeIndex,
+ uint256 typeIndex,
+ bytes32 r,
+ bytes32 s,
+ bytes32 x,
+ bytes32 y
+ ) internal view returns (bool) {
+ return verify(
+ challenge,
+ requireUserVerification,
+ WebAuthnAuth(authenticatorData, clientDataJSON, challengeIndex, typeIndex, r, s),
+ x,
+ y
+ );
+ }
+
+ /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
+ /* ENCODING / DECODING HELPERS */
+ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
+
+ /// @dev Returns `abi.encode(auth)`.
+ function encodeAuth(
+ WebAuthnAuth memory auth
+ ) internal pure returns (bytes memory) {
+ return abi.encode(auth);
+ }
+
+ /// @dev Performs a best-effort attempt to `abi.decode(auth)`. Won't revert.
+ /// If any fields cannot be successfully extracted, `decoded` will not be populated,
+ /// which will cause `verify` to return false (as `clientDataJSON` is empty).
+ function tryDecodeAuth(
+ bytes memory encodedAuth
+ ) internal pure returns (WebAuthnAuth memory decoded) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ for { let n := mload(encodedAuth) } iszero(lt(n, 0xc0)) { } {
+ let o := add(encodedAuth, 0x20) // Start of `encodedAuth`'s bytes.
+ let e := add(o, n) // End of `encodedAuth` in memory.
+ let p := add(mload(o), o) // Start of `encodedAuth`.
+ if or(gt(add(p, 0xc0), e), lt(p, o)) { break }
+ let authenticatorData := add(mload(p), p)
+ let clientDataJSON := add(mload(add(p, 0x20)), p)
+ if or(or(gt(authenticatorData, e), lt(authenticatorData, p)), or(gt(clientDataJSON, e), lt(clientDataJSON, p)))
+ {
+ break
+ }
+ if or(
+ gt(add(add(authenticatorData, 0x20), mload(authenticatorData)), e),
+ gt(add(add(clientDataJSON, 0x20), mload(clientDataJSON)), e)
+ ) { break }
+ mstore(decoded, authenticatorData) // `authenticatorData`.
+ mstore(add(decoded, 0x20), clientDataJSON) // `clientDataJSON`.
+ mstore(add(decoded, 0x40), mload(add(p, 0x40))) // `challengeIndex`.
+ mstore(add(decoded, 0x60), mload(add(p, 0x60))) // `typeIndex`.
+ mstore(add(decoded, 0x80), mload(add(p, 0x80))) // `r`.
+ mstore(add(decoded, 0xa0), mload(add(p, 0xa0))) // `s`.
+ break
+ }
+ }
+ }
+
+ /// @dev Returns the compact encoding of `auth`:
+ /// ```
+ /// abi.encodePacked(
+ /// uint16(auth.authenticatorData.length),
+ /// bytes(auth.authenticatorData),
+ /// bytes(auth.clientDataJSON),
+ /// uint16(auth.challengeIndex),
+ /// uint16(auth.typeIndex),
+ /// bytes32(auth.r),
+ /// bytes32(auth.s)
+ /// )
+ /// ```
+ /// Returns the empty string if any length or index exceeds 16 bits.
+ function tryEncodeAuthCompact(
+ WebAuthnAuth memory auth
+ ) internal pure returns (bytes memory result) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ function copyBytes(o_, s_, c_) -> _e {
+ mstore(o_, shl(240, mload(s_)))
+ o_ := add(o_, c_)
+ _e := add(o_, mload(s_)) // The end of the bytes.
+ for { let d_ := sub(add(0x20, s_), o_) } 1 { } {
+ mstore(o_, mload(add(d_, o_)))
+ o_ := add(o_, 0x20)
+ if iszero(lt(o_, _e)) { break }
+ }
+ }
+ let clientDataJSON := mload(add(0x20, auth))
+ let c := mload(add(0x40, auth)) // `challengeIndex`.
+ let t := mload(add(0x60, auth)) // `typeIndex`.
+ // If none of the lengths are more than `0xffff`.
+ if iszero(shr(16, or(or(t, c), or(mload(mload(auth)), mload(clientDataJSON))))) {
+ result := mload(0x40)
+ // `authenticatorData`, `clientDataJSON`.
+ let o := copyBytes(copyBytes(add(result, 0x20), mload(auth), 2), clientDataJSON, 0)
+ mstore(o, or(shl(240, c), shl(224, t))) // `challengeIndex`, `typeIndex`.
+ mstore(add(o, 0x04), mload(add(0x80, auth))) // `r`.
+ mstore(add(o, 0x24), mload(add(0xa0, auth))) // `s`.
+ mstore(result, sub(add(o, 0x24), result)) // Store the length.
+ mstore(add(o, 0x44), 0) // Zeroize the slot after the string.
+ mstore(0x40, add(o, 0x64)) // Allocate memory .
+ }
+ }
+ }
+
+ /// @dev Approximately the same gas as `tryDecodeAuth`, but helps save on calldata.
+ /// If any fields cannot be successfully extracted, `decoded` will not be populated,
+ /// which will cause `verify` to return false (as `clientDataJSON` is empty).
+ function tryDecodeAuthCompact(
+ bytes memory encodedAuth
+ ) internal pure returns (WebAuthnAuth memory decoded) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ function extractBytes(o_, l_) -> _m {
+ _m := mload(0x40) // Grab the free memory pointer.
+ let s_ := add(_m, 0x20)
+ for { let i_ := 0 } 1 { } {
+ mstore(add(s_, i_), mload(add(o_, i_)))
+ i_ := add(i_, 0x20)
+ if iszero(lt(i_, l_)) { break }
+ }
+ mstore(_m, l_) // Store the length.
+ mstore(add(l_, s_), 0) // Zeroize the slot after the string.
+ mstore(0x40, add(0x20, add(l_, s_))) // Allocate memory.
+ }
+ let n := mload(encodedAuth)
+ if iszero(lt(n, 0x46)) {
+ let o := add(encodedAuth, 0x20) // Start of `encodedAuth`'s bytes.
+ let e := add(o, n) // End of `encodedAuth` in memory.
+ n := shr(240, mload(o)) // Length of `authenticatorData`.
+ let a := add(o, 0x02) // Start of `authenticatorData`.
+ let c := add(a, n) // Start of `clientDataJSON`.
+ let j := sub(e, 0x44) // Start of `challengeIndex`.
+ if iszero(gt(c, j)) {
+ mstore(decoded, extractBytes(a, n)) // `authenticatorData`.
+ mstore(add(decoded, 0x20), extractBytes(c, sub(j, c))) // `clientDataJSON`.
+ mstore(add(decoded, 0x40), shr(240, mload(j))) // `challengeIndex`.
+ mstore(add(decoded, 0x60), shr(240, mload(add(j, 0x02)))) // `typeIndex`.
+ mstore(add(decoded, 0x80), mload(add(j, 0x04))) // `r`.
+ mstore(add(decoded, 0xa0), mload(add(j, 0x24))) // `s`.
+ }
+ }
+ }
+ }
+
+ /// @dev Calldata variant of `tryDecodeAuthCompact`.
+ function tryDecodeAuthCompactCalldata(
+ bytes calldata encodedAuth
+ ) internal pure returns (WebAuthnAuth memory decoded) {
+ /// @solidity memory-safe-assembly
+ assembly {
+ function extractBytes(o_, l_) -> _m {
+ _m := mload(0x40) // Grab the free memory pointer.
+ let s_ := add(_m, 0x20)
+ calldatacopy(s_, o_, l_)
+ mstore(_m, l_) // Store the length.
+ mstore(add(l_, s_), 0) // Zeroize the slot after the string.
+ mstore(0x40, add(0x20, add(l_, s_))) // Allocate memory.
+ }
+ if iszero(lt(encodedAuth.length, 0x46)) {
+ let e := add(encodedAuth.offset, encodedAuth.length) // End of `encodedAuth`.
+ let n := shr(240, calldataload(encodedAuth.offset)) // Length of `authenticatorData`.
+ let a := add(encodedAuth.offset, 0x02) // Start of `authenticatorData`.
+ let c := add(a, n) // Start of `clientDataJSON`.
+ let j := sub(e, 0x44) // Start of `challengeIndex`.
+ if iszero(gt(c, j)) {
+ mstore(decoded, extractBytes(a, n)) // `authenticatorData`.
+ mstore(add(decoded, 0x20), extractBytes(c, sub(j, c))) // `clientDataJSON`.
+ mstore(add(decoded, 0x40), shr(240, calldataload(j))) // `challengeIndex`.
+ mstore(add(decoded, 0x60), shr(240, calldataload(add(j, 0x02)))) // `typeIndex`.
+ mstore(add(decoded, 0x80), calldataload(add(j, 0x04))) // `r`.
+ mstore(add(decoded, 0xa0), calldataload(add(j, 0x24))) // `s`.
+ }
+ }
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/Factory.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/Factory.t.sol
new file mode 100644
index 000000000..b9577de08
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/Factory.t.sol
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Factory } from "../src/Factory.sol";
+import { AdvTest } from "./utils/TestUtils.sol";
+
+contract FactoryTest is AdvTest {
+
+ Factory factory;
+
+ function setUp() external {
+ factory = new Factory();
+ }
+
+ function test_deploy(address _mainModule, bytes32 _salt) external {
+ address result = factory.deploy(_mainModule, _salt);
+ assertNotEq(result.code.length, 0);
+ }
+
+ function test_deployTwice(address _mainModule, bytes32 _salt) external {
+ factory.deploy(_mainModule, _salt);
+ vm.expectRevert(abi.encodeWithSelector(Factory.DeployFailed.selector, _mainModule, _salt));
+ factory.deploy(_mainModule, _salt);
+ }
+
+ function test_deployForwardValue(address _mainModule, bytes32 _salt, uint256 _value) external {
+ vm.deal(address(this), _value);
+ address result = factory.deploy{ value: _value }(_mainModule, _salt);
+ assertEq(result.balance, _value);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/Guest.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/Guest.t.sol
new file mode 100644
index 000000000..5ad438bd8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/Guest.t.sol
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Guest } from "../src/Guest.sol";
+
+import { Calls } from "../src/modules/Calls.sol";
+import { Payload } from "../src/modules/Payload.sol";
+import { PrimitivesRPC } from "./utils/PrimitivesRPC.sol";
+import { AdvTest } from "./utils/TestUtils.sol";
+
+struct GuestPayload {
+ bool noChainId;
+ Payload.Call[] calls;
+ uint160 space;
+ uint56 nonce;
+}
+
+function toDecodedGuestPayload(
+ GuestPayload memory p
+) pure returns (Payload.Decoded memory d) {
+ d.kind = Payload.KIND_TRANSACTIONS;
+ d.calls = p.calls;
+ d.space = p.space;
+ d.nonce = p.nonce;
+}
+
+contract GuestTest is AdvTest {
+
+ Guest public guest;
+
+ event CallSucceeded(bytes32 _opHash, uint256 _index);
+ event CallFailed(bytes32 _opHash, uint256 _index, bytes _returnData);
+ event CallAborted(bytes32 _opHash, uint256 _index, bytes _returnData);
+ event CallSkipped(bytes32 _opHash, uint256 _index);
+
+ function setUp() external {
+ guest = new Guest();
+ }
+
+ function test_fallback(
+ GuestPayload memory p
+ ) external {
+ vm.assume(p.calls.length < 5 && p.calls.length > 0);
+ Payload.Decoded memory decoded = toDecodedGuestPayload(p);
+ boundToLegalPayload(decoded);
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = 0; // No ETH transfers allowed
+ decoded.calls[i].delegateCall = false; // No delegate calls allowed
+ decoded.calls[i].behaviorOnError = bound(decoded.calls[i].behaviorOnError, 0, 2);
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+ }
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+
+ bytes32 opHash = Payload.hashFor(decoded, address(guest));
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ if (decoded.calls[i].onlyFallback) {
+ vm.expectEmit(true, true, true, true);
+ emit CallSkipped(opHash, i);
+ } else {
+ vm.expectCall(decoded.calls[i].to, decoded.calls[i].data);
+ // vm.expectEmit(true, true, true, true);
+ // emit CallSucceeded(opHash, i);
+ }
+ }
+ (bool ok,) = address(guest).call(packed);
+ assertTrue(ok);
+ }
+
+ function test_notEnoughGas(GuestPayload memory p, uint256 callIndex) external {
+ vm.assume(p.calls.length > 0);
+ callIndex = bound(callIndex, 0, p.calls.length - 1);
+
+ Payload.Decoded memory decoded = toDecodedGuestPayload(p);
+ boundToLegalPayload(decoded);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = 0;
+ decoded.calls[i].delegateCall = false;
+
+ if (i == callIndex) {
+ // Only set high gas limit for the specified call
+ uint256 gasLimit = bound(decoded.calls[i].gasLimit, gasleft() + 1, type(uint256).max);
+ decoded.calls[i].gasLimit = gasLimit;
+ decoded.calls[i].onlyFallback = false;
+ } else {
+ // Set normal gas limits for other calls
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+ }
+ }
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+
+ vm.expectRevert();
+ (bool ok,) = address(guest).call(packed);
+ assertTrue(ok);
+ }
+
+ function test_delegateCallNotAllowed(GuestPayload memory p, uint256 callIndex) external {
+ vm.assume(p.calls.length > 0);
+ callIndex = bound(callIndex, 0, p.calls.length - 1);
+
+ Payload.Decoded memory decoded = toDecodedGuestPayload(p);
+ boundToLegalPayload(decoded);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = 0;
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+
+ if (i == callIndex) {
+ // Set delegateCall to true for the specified call
+ decoded.calls[i].delegateCall = true;
+ decoded.calls[i].onlyFallback = false;
+ } else {
+ decoded.calls[i].delegateCall = false;
+ }
+ }
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+
+ vm.expectRevert(abi.encodeWithSelector(Guest.DelegateCallNotAllowed.selector, callIndex));
+ (bool ok,) = address(guest).call(packed);
+ assertTrue(ok);
+ }
+
+ function test_callFailsWithIgnoreBehavior(GuestPayload memory p, uint256 callIndex) external {
+ vm.assume(p.calls.length > 0);
+ callIndex = bound(callIndex, 0, p.calls.length - 1);
+
+ Payload.Decoded memory decoded = toDecodedGuestPayload(p);
+ boundToLegalPayload(decoded);
+
+ decoded.calls[callIndex].to = boundNoPrecompile(decoded.calls[callIndex].to);
+ address failureAddress = decoded.calls[callIndex].to;
+ bytes32 failureDataHash = keccak256(decoded.calls[callIndex].data);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = 0;
+ decoded.calls[i].delegateCall = false;
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+
+ if (i == callIndex) {
+ decoded.calls[i].behaviorOnError = Payload.BEHAVIOR_IGNORE_ERROR;
+ decoded.calls[i].onlyFallback = false;
+ } else if (decoded.calls[i].to == failureAddress) {
+ decoded.calls[i].behaviorOnError = Payload.BEHAVIOR_IGNORE_ERROR;
+ }
+ }
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(guest));
+
+ // Mock the call to fail with some revert data
+ bytes memory revertData = abi.encodeWithSignature("Error(string)", "Test error");
+ vm.mockCallRevert(decoded.calls[callIndex].to, decoded.calls[callIndex].data, revertData);
+
+ bool errorFlag = false;
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ vm.expectEmit(true, true, true, true);
+
+ if (!errorFlag && decoded.calls[i].onlyFallback) {
+ emit CallSkipped(opHash, i);
+ } else if (decoded.calls[i].to == failureAddress && keccak256(decoded.calls[i].data) == failureDataHash) {
+ emit CallFailed(opHash, i, revertData);
+ errorFlag = true;
+ } else {
+ emit CallSucceeded(opHash, i);
+ vm.expectCall(decoded.calls[i].to, decoded.calls[i].data);
+ errorFlag = false;
+ }
+ }
+
+ (bool ok,) = address(guest).call(packed);
+ assertTrue(ok);
+ }
+
+ function test_callFailsWithRevertBehavior(GuestPayload memory p, uint256 callIndex) external {
+ vm.assume(p.calls.length > 0);
+ callIndex = bound(callIndex, 0, p.calls.length - 1);
+
+ Payload.Decoded memory decoded = toDecodedGuestPayload(p);
+ boundToLegalPayload(decoded);
+
+ decoded.calls[callIndex].to = boundNoPrecompile(decoded.calls[callIndex].to);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = 0;
+ decoded.calls[i].delegateCall = false;
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+
+ if (decoded.calls[i].to == decoded.calls[callIndex].to && i != callIndex) {
+ decoded.calls[i].behaviorOnError = Payload.BEHAVIOR_IGNORE_ERROR;
+ }
+
+ if (i == callIndex) {
+ decoded.calls[i].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ decoded.calls[i].onlyFallback = false;
+ }
+ }
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+
+ // Mock the call to fail with some revert data
+ bytes memory revertData = abi.encodeWithSignature("Error(string)", "Test error");
+ vm.mockCallRevert(decoded.calls[callIndex].to, decoded.calls[callIndex].data, revertData);
+
+ // Expect the revert
+ vm.expectRevert(abi.encodeWithSelector(Calls.Reverted.selector, decoded, callIndex, revertData));
+
+ (bool ok,) = address(guest).call(packed);
+ assertTrue(ok);
+ }
+
+ function test_callFailsWithAbortBehavior(GuestPayload memory p, uint256 callIndex) external {
+ vm.assume(p.calls.length > 0);
+ callIndex = bound(callIndex, 0, p.calls.length - 1);
+
+ Payload.Decoded memory decoded = toDecodedGuestPayload(p);
+ boundToLegalPayload(decoded);
+
+ decoded.calls[callIndex].to = boundNoPrecompile(decoded.calls[callIndex].to);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = 0;
+ decoded.calls[i].delegateCall = false;
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+
+ if (decoded.calls[i].to == decoded.calls[callIndex].to && i != callIndex) {
+ decoded.calls[i].behaviorOnError = Payload.BEHAVIOR_IGNORE_ERROR;
+ }
+
+ if (i == callIndex) {
+ decoded.calls[i].behaviorOnError = Payload.BEHAVIOR_ABORT_ON_ERROR;
+ decoded.calls[i].onlyFallback = false;
+ }
+ }
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(guest));
+
+ // Mock the call to fail with some revert data
+ bytes memory revertData = abi.encodeWithSignature("Error(string)", "Test error");
+ vm.mockCallRevert(decoded.calls[callIndex].to, decoded.calls[callIndex].data, revertData);
+
+ // Expect the abort event
+ vm.expectEmit(true, true, true, true);
+ emit CallAborted(opHash, callIndex, revertData);
+
+ (bool ok,) = address(guest).call(packed);
+ assertTrue(ok);
+ }
+
+ function test_forwardPayment(uint256 _value1, uint256 _value2) external {
+ address to1 = address(0x100001);
+ address to2 = address(0x100002);
+
+ _value1 = bound(_value1, 0, type(uint128).max);
+ _value2 = bound(_value2, 0, type(uint128).max);
+
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_TRANSACTIONS;
+ payload.calls = new Payload.Call[](2);
+ payload.calls[0].to = to1;
+ payload.calls[0].value = _value1;
+ payload.calls[1].to = to2;
+ payload.calls[1].value = _value2;
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, payload);
+
+ uint256 total = _value1 + _value2;
+ vm.deal(address(this), total);
+ (bool ok,) = address(guest).call{ value: total }(packed);
+ assertTrue(ok);
+
+ assertEq(address(this).balance, 0);
+
+ assertEq(address(to1).balance, _value1);
+ assertEq(address(to2).balance, _value2);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/Stage1Module.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/Stage1Module.t.sol
new file mode 100644
index 000000000..cf99dbb5e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/Stage1Module.t.sol
@@ -0,0 +1,1305 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Factory } from "../src/Factory.sol";
+import { Stage1Module } from "../src/Stage1Module.sol";
+import { Stage2Module } from "../src/Stage2Module.sol";
+
+import { Payload } from "../src/modules/Payload.sol";
+
+import { BaseAuth } from "../src/modules/auth/BaseAuth.sol";
+
+import { SelfAuth } from "../src/modules/auth/SelfAuth.sol";
+
+import { Calls } from "../src/modules/Calls.sol";
+import { Stage1Auth } from "../src/modules/auth/Stage1Auth.sol";
+import { IPartialAuth } from "../src/modules/interfaces/IPartialAuth.sol";
+
+import { ISapient } from "../src/modules/interfaces/ISapient.sol";
+import { PrimitivesRPC } from "./utils/PrimitivesRPC.sol";
+import { AdvTest } from "./utils/TestUtils.sol";
+
+import { CanReenter } from "test/mocks/CanReenter.sol";
+
+contract TestStage1Module is AdvTest {
+
+ event ImageHashUpdated(bytes32 newImageHash);
+
+ Factory public factory = new Factory();
+ Stage1Module public stage1Module = new Stage1Module(address(factory), address(0));
+
+ event StaticSignatureSet(bytes32 _hash, address _address, uint96 _timestamp);
+
+ function test_fails_on_low_weight(
+ uint16 _threshold,
+ uint56 _checkpoint,
+ uint8 _weight,
+ uint256 _pk,
+ bytes32 _digest,
+ bool _noChainId
+ ) external {
+ _weight = uint8(bound(_weight, 1, type(uint8).max));
+ _threshold = uint16(bound(_threshold, 1, _weight));
+ _pk = boundPk(_pk);
+
+ address signer = vm.addr(_pk);
+
+ string memory config;
+
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(signer), ":", vm.toString(_weight)));
+ config = PrimitivesRPC.newConfig(vm, _threshold, _checkpoint, ce);
+ }
+
+ bytes32 configHash = PrimitivesRPC.getImageHash(vm, config);
+
+ // Deploy wallet for that config
+ address payable wallet = payable(factory.deploy(address(stage1Module), configHash));
+
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = _digest;
+ payload.noChainId = _noChainId;
+
+ // Create a signature with only nodes
+ bytes memory signature = PrimitivesRPC.toEncodedSignature(vm, config, "", !_noChainId);
+
+ // Call isValidSignature and expect it to fail
+ vm.expectRevert(abi.encodeWithSelector(BaseAuth.InvalidSignatureWeight.selector, _threshold, 0));
+ Stage1Module(wallet).isValidSignature(_digest, signature);
+ }
+
+ function test_1271_single_signer(
+ uint16 _threshold,
+ uint56 _checkpoint,
+ uint8 _weight,
+ uint256 _pk,
+ bytes32 _digest,
+ bool _noChainId
+ ) external {
+ _threshold = uint16(bound(_threshold, 0, _weight));
+ _pk = boundPk(_pk);
+
+ address signer = vm.addr(_pk);
+
+ string memory config;
+
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(signer), ":", vm.toString(_weight)));
+ config = PrimitivesRPC.newConfig(vm, _threshold, _checkpoint, ce);
+ }
+
+ bytes32 configHash = PrimitivesRPC.getImageHash(vm, config);
+
+ // Deploy wallet for that config
+ address payable wallet = payable(factory.deploy(address(stage1Module), configHash));
+
+ // Should predict the address of the wallet using the SDK
+ address predictedWallet = PrimitivesRPC.getAddress(vm, configHash, address(factory), address(stage1Module));
+ assertEq(wallet, predictedWallet);
+
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = _digest;
+ payload.noChainId = _noChainId;
+
+ // Sign the config
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(_pk, Payload.hashFor(payload, wallet));
+
+ bytes memory signature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(abi.encodePacked(vm.toString(signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))),
+ !_noChainId
+ );
+
+ // Call isValidSignature
+ bytes4 result = Stage1Module(wallet).isValidSignature(_digest, signature);
+ assertEq(result, bytes4(0x1626ba7e));
+ }
+
+ struct test_update_config_params {
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ uint256 pk;
+ bool noChainId;
+ // Next config parameters
+ uint16 nextThreshold;
+ uint56 nextCheckpoint;
+ uint8 nextWeight;
+ uint256 nextPk;
+ // Test transaction parameters
+ bytes32 digest;
+ }
+
+ struct test_update_config_vars {
+ address ogSigner;
+ address nextSigner;
+ string ogConfig;
+ string nextConfig;
+ bytes32 ogConfigHash;
+ bytes32 nextConfigHash;
+ Payload.Decoded updateConfigPayload;
+ bytes updateConfigSignature;
+ bytes updateConfigPackedPayload;
+ Payload.Decoded useNewImageHashPayload;
+ bytes useNewImageHashSignature;
+ }
+
+ function test_update_config(
+ test_update_config_params memory params
+ ) external {
+ params.pk = boundPk(params.pk);
+ params.nextPk = boundPk(params.nextPk);
+ params.threshold = uint16(bound(params.threshold, 0, params.weight));
+ params.nextThreshold = uint16(bound(params.nextThreshold, 0, params.nextWeight));
+
+ test_update_config_vars memory vars;
+
+ vars.ogSigner = vm.addr(params.pk);
+
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.ogSigner), ":", vm.toString(params.weight)));
+ vars.ogConfig = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ vars.ogConfigHash = PrimitivesRPC.getImageHash(vm, vars.ogConfig);
+
+ // Deploy wallet for that config
+ address payable wallet = payable(factory.deploy(address(stage1Module), vars.ogConfigHash));
+
+ vars.nextSigner = vm.addr(params.nextPk);
+
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.nextSigner), ":", vm.toString(params.nextWeight)));
+ vars.nextConfig = PrimitivesRPC.newConfig(vm, params.nextThreshold, params.nextCheckpoint, ce);
+ }
+
+ vars.nextConfigHash = PrimitivesRPC.getImageHash(vm, vars.nextConfig);
+
+ // Update configuration to the next config
+ vars.updateConfigPayload.kind = Payload.KIND_TRANSACTIONS;
+ vars.updateConfigPayload.calls = new Payload.Call[](1);
+ vars.updateConfigPayload.calls[0] = Payload.Call({
+ to: address(wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, vars.nextConfigHash),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ vars.updateConfigPayload.noChainId = params.noChainId;
+
+ {
+ // Sign the payload
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(params.pk, Payload.hashFor(vars.updateConfigPayload, wallet));
+
+ // Call updateConfig
+ vars.updateConfigSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.ogConfig,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.ogSigner), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ !params.noChainId
+ );
+ }
+
+ // Pack payload
+ vars.updateConfigPackedPayload = PrimitivesRPC.toPackedPayload(vm, vars.updateConfigPayload);
+
+ // Perform updateConfig
+ vm.expectEmit(true, true, false, true, wallet);
+ emit ImageHashUpdated(vars.nextConfigHash);
+ Stage1Module(wallet).execute(vars.updateConfigPackedPayload, vars.updateConfigSignature);
+
+ // Now the wallet should be at stage 2
+ // and its imageHash should be updated
+ assertEq(Stage1Module(wallet).getImplementation(), stage1Module.STAGE_2_IMPLEMENTATION());
+ assertEq(Stage2Module(wallet).imageHash(), vars.nextConfigHash);
+
+ // Now try to use the new imageHash
+ vars.useNewImageHashPayload.kind = Payload.KIND_DIGEST;
+ vars.useNewImageHashPayload.digest = params.digest;
+
+ // Sign the payload
+ {
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(params.nextPk, Payload.hashFor(vars.useNewImageHashPayload, wallet));
+
+ vars.useNewImageHashSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.nextConfig,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.nextSigner), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ true
+ );
+ }
+
+ bytes4 result = Stage2Module(wallet).isValidSignature(params.digest, vars.useNewImageHashSignature);
+ assertEq(result, bytes4(0x1626ba7e));
+ }
+
+ function test_receiveETH_stage1() external {
+ address payable wallet = payable(factory.deploy(address(stage1Module), bytes32(0)));
+ vm.deal(address(this), 1 ether);
+ wallet.transfer(1 ether);
+ assertEq(address(wallet).balance, 1 ether);
+ }
+
+ struct test_receiveETH_stage2_params {
+ uint256 pk;
+ uint256 nextPk;
+ uint16 threshold;
+ uint16 nextThreshold;
+ uint56 checkpoint;
+ }
+
+ struct test_receiveETH_stage2_vars {
+ address signer;
+ address payable wallet;
+ bytes updateConfigSignature;
+ bytes updateConfigPackedPayload;
+ string ogCe;
+ string ogConfig;
+ string nextCe;
+ string nextConfig;
+ bytes32 ogConfigHash;
+ bytes32 nextConfigHash;
+ }
+
+ function test_receiveETH_stage2(
+ test_receiveETH_stage2_params memory params
+ ) external {
+ params.pk = boundPk(params.pk);
+
+ test_receiveETH_stage2_vars memory vars;
+ vars.signer = vm.addr(params.pk);
+
+ // Original config (stage1)
+ vars.ogCe = string(abi.encodePacked("signer:", vm.toString(vars.signer), ":1"));
+ vars.ogConfig = PrimitivesRPC.newConfig(vm, 1, 0, vars.ogCe);
+ vars.ogConfigHash = PrimitivesRPC.getImageHash(vm, vars.ogConfig);
+
+ // Deploy wallet in stage1
+ vars.wallet = payable(factory.deploy(address(stage1Module), vars.ogConfigHash));
+
+ // Next config (what we'll update to)
+ vars.nextCe = string(abi.encodePacked("signer:", vm.toString(vars.signer), ":1"));
+ vars.nextConfig = PrimitivesRPC.newConfig(vm, 1, 1, vars.nextCe);
+ vars.nextConfigHash = PrimitivesRPC.getImageHash(vm, vars.nextConfig);
+
+ // Construct the payload to update the imageHash (which transitions us to stage2)
+ Payload.Decoded memory updateConfigPayload;
+ updateConfigPayload.kind = Payload.KIND_TRANSACTIONS;
+ updateConfigPayload.calls = new Payload.Call[](1);
+ updateConfigPayload.calls[0] = Payload.Call({
+ to: address(vars.wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, vars.nextConfigHash),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Sign the payload using the original config
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(params.pk, Payload.hashFor(updateConfigPayload, vars.wallet));
+ vars.updateConfigSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.ogConfig,
+ string(
+ abi.encodePacked(vm.toString(vars.signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ ),
+ true
+ );
+
+ // Pack the payload and execute
+ vars.updateConfigPackedPayload = PrimitivesRPC.toPackedPayload(vm, updateConfigPayload);
+ vm.expectEmit(true, true, false, true, vars.wallet);
+ emit ImageHashUpdated(vars.nextConfigHash);
+ Stage1Module(vars.wallet).execute(vars.updateConfigPackedPayload, vars.updateConfigSignature);
+
+ // Confirm that the wallet is now running stage2
+ assertEq(Stage1Module(vars.wallet).getImplementation(), stage1Module.STAGE_2_IMPLEMENTATION());
+
+ // Send 1 ether to the newly upgraded wallet
+ vm.deal(address(this), 1 ether);
+ vars.wallet.transfer(1 ether);
+
+ // Check that the wallet received the ether
+ assertEq(address(vars.wallet).balance, 1 ether);
+ }
+
+ function test_static_signature_any_address(
+ bytes32 _digest,
+ bytes32 _imageHash,
+ uint256 _timestamp,
+ uint256 _validUntil,
+ address _otherCaller
+ ) external {
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = _digest;
+
+ _timestamp = bound(_timestamp, 0, type(uint64).max);
+ _validUntil = bound(_validUntil, _timestamp + 1, type(uint96).max);
+
+ vm.warp(_timestamp);
+
+ // Create a new wallet using imageHash
+ address payable wallet = payable(factory.deploy(address(stage1Module), _imageHash));
+
+ // Set the static signature
+ vm.prank(wallet);
+ vm.expectEmit(true, true, false, true, wallet);
+ emit StaticSignatureSet(Payload.hashFor(payload, wallet), address(0), uint96(_validUntil));
+ Stage1Module(wallet).setStaticSignature(Payload.hashFor(payload, wallet), address(0), uint96(_validUntil));
+
+ (address addr, uint256 timestamp) = Stage1Module(wallet).getStaticSignature(Payload.hashFor(payload, wallet));
+ assertEq(addr, address(0));
+ assertEq(timestamp, _validUntil);
+
+ // Call isValidSignature and expect it to succeed
+ bytes4 result = Stage1Module(wallet).isValidSignature(_digest, hex"80");
+ assertEq(result, bytes4(0x1626ba7e));
+
+ // Even if called from other caller
+ vm.prank(_otherCaller);
+ result = Stage1Module(wallet).isValidSignature(_digest, hex"80");
+ assertEq(result, bytes4(0x1626ba7e));
+ }
+
+ function test_static_signature_specific_address(
+ bytes32 _digest,
+ bytes32 _imageHash,
+ uint256 _timestamp,
+ uint256 _validUntil,
+ address _onlyAddress,
+ address _otherCaller
+ ) external {
+ vm.assume(_onlyAddress != address(0) && _onlyAddress != _otherCaller);
+
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = _digest;
+
+ _timestamp = bound(_timestamp, 0, type(uint64).max);
+ _validUntil = bound(_validUntil, _timestamp + 1, type(uint96).max);
+
+ vm.warp(_timestamp);
+
+ // Create a new wallet using imageHash
+ address payable wallet = payable(factory.deploy(address(stage1Module), _imageHash));
+
+ // Set the static signature
+ vm.prank(wallet);
+ vm.expectEmit(true, true, false, true, wallet);
+ emit StaticSignatureSet(Payload.hashFor(payload, wallet), _onlyAddress, uint96(_validUntil));
+ Stage1Module(wallet).setStaticSignature(Payload.hashFor(payload, wallet), _onlyAddress, uint96(_validUntil));
+
+ (address addr, uint256 timestamp) = Stage1Module(wallet).getStaticSignature(Payload.hashFor(payload, wallet));
+ assertEq(addr, _onlyAddress);
+ assertEq(timestamp, _validUntil);
+
+ // Call isValidSignature from _onlyAddress should succeed
+ vm.prank(_onlyAddress);
+ bytes4 result = Stage1Module(wallet).isValidSignature(_digest, hex"80");
+ assertEq(result, bytes4(0x1626ba7e));
+
+ // Call isValidSignature from _otherCaller should fail
+ vm.prank(_otherCaller);
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ BaseAuth.InvalidStaticSignatureWrongCaller.selector,
+ Payload.hashFor(payload, wallet),
+ _otherCaller,
+ _onlyAddress
+ )
+ );
+ Stage1Module(wallet).isValidSignature(_digest, hex"80");
+ }
+
+ function test_reverts_invalid_static_signature_expired(
+ bytes32 _digest,
+ bytes32 _imageHash,
+ uint256 _startTime,
+ uint256 _validUntil
+ ) external {
+ // Ensure validUntil is strictly after startTime and within uint96 range
+ _startTime = bound(_startTime, 0, type(uint96).max - 1);
+ _validUntil = bound(_validUntil, _startTime + 1, type(uint96).max);
+
+ // Set the current time to _startTime
+ vm.warp(_startTime);
+
+ // Create a new wallet
+ address payable wallet = payable(factory.deploy(address(stage1Module), _imageHash));
+
+ // Prepare the payload and calculate its hash
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = _digest;
+ bytes32 opHash = Payload.hashFor(payload, wallet);
+
+ // Set the static signature from the wallet itself, valid until _validUntil
+ // Use address(0) to allow any caller before expiration
+ vm.prank(wallet);
+ vm.expectEmit(true, true, false, true, wallet);
+ emit StaticSignatureSet(opHash, address(0), uint96(_validUntil));
+ Stage1Module(wallet).setStaticSignature(opHash, address(0), uint96(_validUntil));
+
+ // Verify it was set correctly
+ (address addr, uint256 timestamp) = Stage1Module(wallet).getStaticSignature(opHash);
+ assertEq(addr, address(0));
+ assertEq(timestamp, _validUntil);
+
+ // --- Test Case 1: Use signature just before expiry (should work) ---
+ vm.warp(_validUntil - 1); // Set time to just before expiration
+ bytes4 result = Stage1Module(wallet).isValidSignature(_digest, hex"80");
+ assertEq(result, bytes4(0x1626ba7e), "Signature should be valid before expiry");
+
+ // --- Test Case 2: Use signature exactly at expiry (should fail) ---
+ vm.warp(_validUntil); // Set time exactly to expiration
+ vm.expectRevert(abi.encodeWithSelector(BaseAuth.InvalidStaticSignatureExpired.selector, opHash, _validUntil));
+ Stage1Module(wallet).isValidSignature(_digest, hex"80");
+
+ // --- Test Case 3: Use signature after expiry (should fail) ---
+ vm.warp(_validUntil + 1); // Set time after expiration
+ vm.expectRevert(abi.encodeWithSelector(BaseAuth.InvalidStaticSignatureExpired.selector, opHash, _validUntil));
+ Stage1Module(wallet).isValidSignature(_digest, hex"80");
+ }
+
+ function test_reverts_set_static_signature_not_self(
+ bytes32 _hash,
+ bytes32 _imageHash,
+ address _sigAddress,
+ uint96 _timestamp,
+ address _caller // The address attempting the call (not the wallet)
+ ) external {
+ // Create a new wallet
+ address payable wallet = payable(factory.deploy(address(stage1Module), _imageHash));
+
+ // Ensure the caller is not the wallet itself
+ vm.assume(_caller != wallet);
+
+ // Attempt to call setStaticSignature from _caller
+ vm.prank(_caller);
+ vm.expectRevert(abi.encodeWithSelector(SelfAuth.OnlySelf.selector, _caller));
+ Stage1Module(wallet).setStaticSignature(_hash, _sigAddress, _timestamp);
+
+ // Verify that the signature was NOT set (should still be default values)
+ (address addr, uint256 ts) = Stage1Module(wallet).getStaticSignature(_hash);
+ assertEq(addr, address(0), "Static signature address should not be set");
+ assertEq(ts, 0, "Static signature timestamp should not be set");
+ }
+
+ struct test_recover_partial_signature_params {
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 signerWeight;
+ uint256 pk;
+ bool signPayload;
+ bool useEthSign;
+ bool noChainId;
+ }
+
+ struct test_recover_partial_signature_vars {
+ address signer;
+ string config;
+ bytes32 configHash;
+ bytes encodedSignature;
+ uint8 v;
+ bytes32 r;
+ bytes32 s;
+ bytes32 payloadHash;
+ address wallet;
+ uint256 expectedWeight;
+ }
+
+ function test_recover_partial_signature(
+ test_recover_partial_signature_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+ params.pk = boundPk(params.pk);
+ params.payload.noChainId = params.noChainId;
+ if (params.signPayload) {
+ params.threshold = uint16(bound(params.threshold, 1, type(uint16).max));
+ params.signerWeight = uint8(bound(params.signerWeight, 0, type(uint8).max));
+ } else {
+ params.threshold = uint16(bound(params.threshold, 0, type(uint16).max));
+ params.signerWeight = uint8(bound(params.signerWeight, 0, type(uint8).max));
+ }
+
+ test_recover_partial_signature_vars memory vars;
+ vars.signer = vm.addr(params.pk);
+
+ string memory ce =
+ string(abi.encodePacked("signer:", vm.toString(vars.signer), ":", vm.toString(params.signerWeight)));
+ vars.config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ vars.configHash = PrimitivesRPC.getImageHash(vm, vars.config);
+
+ vars.wallet = factory.deploy(address(stage1Module), vars.configHash);
+
+ vars.payloadHash = Payload.hashFor(params.payload, vars.wallet);
+ string memory signatures = "";
+ vars.expectedWeight = 0;
+
+ if (params.signPayload) {
+ bytes32 hashToSign = vars.payloadHash;
+ if (params.useEthSign) {
+ hashToSign = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", vars.payloadHash));
+ }
+ (vars.v, vars.r, vars.s) = vm.sign(params.pk, hashToSign);
+
+ string memory signatureType = params.useEthSign ? ":eth_sign:" : ":hash:";
+ signatures = string(
+ abi.encodePacked(
+ vm.toString(vars.signer),
+ signatureType,
+ vm.toString(vars.r),
+ ":",
+ vm.toString(vars.s),
+ ":",
+ vm.toString(vars.v)
+ )
+ );
+ vars.expectedWeight = params.signerWeight;
+ }
+
+ vars.encodedSignature = PrimitivesRPC.toEncodedSignature(vm, vars.config, signatures, !params.noChainId);
+
+ (
+ uint256 recoveredThreshold,
+ uint256 recoveredWeight,
+ bool recoveredIsValidImage,
+ bytes32 recoveredImageHash,
+ uint256 recoveredCheckpoint,
+ bytes32 recoveredOpHash
+ ) = IPartialAuth(vars.wallet).recoverPartialSignature(params.payload, vars.encodedSignature);
+
+ assertEq(recoveredThreshold, params.threshold, "Threshold mismatch");
+ assertEq(recoveredWeight, vars.expectedWeight, "Weight mismatch");
+ bool expectedIsValidImage = address(
+ uint160(uint256(keccak256(abi.encodePacked(hex"ff", factory, recoveredImageHash, stage1Module.INIT_CODE_HASH()))))
+ ) == vars.wallet;
+ assertEq(recoveredIsValidImage, expectedIsValidImage, "isValidImage mismatch");
+ assertEq(recoveredImageHash, vars.configHash, "ImageHash mismatch");
+ assertEq(recoveredCheckpoint, params.checkpoint, "Checkpoint mismatch");
+ assertEq(recoveredOpHash, vars.payloadHash, "OpHash mismatch");
+ }
+
+ struct test_invalid_is_valid_signature_params {
+ bytes32 digest;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ uint256 intendedPk;
+ uint256 actualPk;
+ bool noChainId;
+ }
+
+ struct test_invalid_is_valid_signature_vars {
+ address intendedSigner;
+ address actualSigner;
+ string config;
+ string badConfig;
+ bytes32 configHash;
+ address payable wallet;
+ Payload.Decoded payload;
+ bytes32 payloadHash;
+ uint8 v;
+ bytes32 r;
+ bytes32 s;
+ bytes encodedSignature;
+ }
+
+ function test_invalid_is_valid_signature(
+ test_invalid_is_valid_signature_params memory params
+ ) external {
+ params.intendedPk = boundPk(params.intendedPk);
+ params.actualPk = boundPk(params.actualPk);
+ vm.assume(params.intendedPk != params.actualPk);
+ params.threshold = uint16(bound(params.threshold, 0, type(uint8).max));
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ test_invalid_is_valid_signature_vars memory vars;
+ vars.intendedSigner = vm.addr(params.intendedPk);
+ vars.actualSigner = vm.addr(params.actualPk);
+
+ string memory ce =
+ string(abi.encodePacked("signer:", vm.toString(vars.intendedSigner), ":", vm.toString(params.weight)));
+ vars.config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ vars.configHash = PrimitivesRPC.getImageHash(vm, vars.config);
+
+ string memory badCe =
+ string(abi.encodePacked("signer:", vm.toString(vars.actualSigner), ":", vm.toString(params.weight)));
+ vars.badConfig = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, badCe);
+
+ vars.wallet = payable(factory.deploy(address(stage1Module), vars.configHash));
+
+ vars.payload.kind = Payload.KIND_DIGEST;
+ vars.payload.digest = params.digest;
+ vars.payload.noChainId = params.noChainId;
+
+ vars.payloadHash = Payload.hashFor(vars.payload, vars.wallet);
+
+ (vars.v, vars.r, vars.s) = vm.sign(params.actualPk, vars.payloadHash);
+
+ string memory signatures = string(
+ abi.encodePacked(
+ vm.toString(vars.actualSigner),
+ ":hash:",
+ vm.toString(vars.r),
+ ":",
+ vm.toString(vars.s),
+ ":",
+ vm.toString(vars.v)
+ )
+ );
+ vars.encodedSignature = PrimitivesRPC.toEncodedSignature(vm, vars.badConfig, signatures, !params.noChainId);
+
+ bytes4 result = Stage1Module(vars.wallet).isValidSignature(params.digest, vars.encodedSignature);
+ assertEq(
+ result,
+ bytes4(0),
+ "isValidSignature should return 0x00000000 for invalid signature (wrong signer -> imageHash mismatch)"
+ );
+ }
+
+ function test_reverts_update_to_zero_image_hash(
+ uint16 _threshold,
+ uint56 _checkpoint,
+ uint8 _weight,
+ uint256 _pk,
+ bool _noChainId
+ ) external {
+ _threshold = uint16(bound(_threshold, 0, _weight));
+ _pk = boundPk(_pk);
+
+ address signer = vm.addr(_pk);
+
+ string memory config;
+
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(signer), ":", vm.toString(_weight)));
+ config = PrimitivesRPC.newConfig(vm, _threshold, _checkpoint, ce);
+ }
+
+ bytes32 configHash = PrimitivesRPC.getImageHash(vm, config);
+
+ // Deploy wallet for that config
+ address payable wallet = payable(factory.deploy(address(stage1Module), configHash));
+
+ // Update configuration to zero imageHash
+ Payload.Decoded memory updateConfigPayload;
+ updateConfigPayload.kind = Payload.KIND_TRANSACTIONS;
+ updateConfigPayload.calls = new Payload.Call[](1);
+ updateConfigPayload.calls[0] = Payload.Call({
+ to: address(wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, bytes32(0)),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ updateConfigPayload.noChainId = _noChainId;
+
+ // Sign the payload
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(_pk, Payload.hashFor(updateConfigPayload, wallet));
+
+ // Call updateConfig
+ bytes memory updateConfigSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(abi.encodePacked(vm.toString(signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))),
+ !_noChainId
+ );
+
+ // Pack payload
+ bytes memory updateConfigPackedPayload = PrimitivesRPC.toPackedPayload(vm, updateConfigPayload);
+
+ bytes memory innerRevert = abi.encodeWithSelector(Stage1Auth.ImageHashIsZero.selector);
+
+ // Attempt to update to zero imageHash and expect revert
+ vm.expectRevert(abi.encodeWithSelector(Calls.Reverted.selector, updateConfigPayload, 0, innerRevert));
+ Stage1Module(wallet).execute(updateConfigPackedPayload, updateConfigSignature);
+ }
+
+ struct test_update_image_hash_twice_params {
+ uint16 threshold1;
+ uint56 checkpoint1;
+ uint8 weight1;
+ uint256 pk1;
+ uint16 threshold2;
+ uint56 checkpoint2;
+ uint8 weight2;
+ uint256 pk2;
+ bool noChainId;
+ }
+
+ struct test_update_image_hash_twice_vars {
+ address signer1;
+ address signer2;
+ string config1;
+ string config2;
+ string config3;
+ bytes32 configHash1;
+ bytes32 configHash2;
+ bytes32 configHash3;
+ address payable wallet;
+ Payload.Decoded updateConfigPayload1;
+ Payload.Decoded updateConfigPayload2;
+ bytes updateConfigSignature1;
+ bytes updateConfigSignature2;
+ bytes updateConfigPackedPayload1;
+ bytes updateConfigPackedPayload2;
+ }
+
+ function test_update_image_hash_twice(
+ test_update_image_hash_twice_params memory params
+ ) external {
+ params.threshold1 = uint16(bound(params.threshold1, 0, params.weight1));
+ params.threshold2 = uint16(bound(params.threshold2, 0, params.weight2));
+ params.pk1 = boundPk(params.pk1);
+ params.pk2 = boundPk(params.pk2);
+
+ test_update_image_hash_twice_vars memory vars;
+ vars.signer1 = vm.addr(params.pk1);
+ vars.signer2 = vm.addr(params.pk2);
+
+ // First config
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer1), ":", vm.toString(params.weight1)));
+ vars.config1 = PrimitivesRPC.newConfig(vm, params.threshold1, params.checkpoint1, ce);
+ }
+ vars.configHash1 = PrimitivesRPC.getImageHash(vm, vars.config1);
+
+ // Deploy wallet with first config
+ vars.wallet = payable(factory.deploy(address(stage1Module), vars.configHash1));
+
+ // Second config
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer2), ":", vm.toString(params.weight2)));
+ vars.config2 = PrimitivesRPC.newConfig(vm, params.threshold2, params.checkpoint2, ce);
+ }
+ vars.configHash2 = PrimitivesRPC.getImageHash(vm, vars.config2);
+
+ // First update
+ vars.updateConfigPayload1.kind = Payload.KIND_TRANSACTIONS;
+ vars.updateConfigPayload1.calls = new Payload.Call[](1);
+ vars.updateConfigPayload1.calls[0] = Payload.Call({
+ to: address(vars.wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, vars.configHash2),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ vars.updateConfigPayload1.noChainId = params.noChainId;
+
+ // Sign the first payload
+ (uint256 v1, bytes32 r1, bytes32 s1) = vm.sign(params.pk1, Payload.hashFor(vars.updateConfigPayload1, vars.wallet));
+
+ // Call first update
+ vars.updateConfigSignature1 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config1,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1), ":hash:", vm.toString(r1), ":", vm.toString(s1), ":", vm.toString(v1)
+ )
+ ),
+ !params.noChainId
+ );
+
+ // Pack first payload
+ vars.updateConfigPackedPayload1 = PrimitivesRPC.toPackedPayload(vm, vars.updateConfigPayload1);
+
+ // Execute first update
+ vm.expectEmit(true, true, false, true, vars.wallet);
+ emit ImageHashUpdated(vars.configHash2);
+ Stage1Module(vars.wallet).execute(vars.updateConfigPackedPayload1, vars.updateConfigSignature1);
+
+ // Verify first update worked
+ assertEq(Stage1Module(vars.wallet).getImplementation(), stage1Module.STAGE_2_IMPLEMENTATION());
+ assertEq(Stage2Module(vars.wallet).imageHash(), vars.configHash2);
+
+ // Third config
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer1), ":", vm.toString(params.weight1)));
+ vars.config3 = PrimitivesRPC.newConfig(vm, params.threshold1, params.checkpoint1, ce);
+ }
+ vars.configHash3 = PrimitivesRPC.getImageHash(vm, vars.config3);
+
+ // Second update
+ vars.updateConfigPayload2.kind = Payload.KIND_TRANSACTIONS;
+ vars.updateConfigPayload2.calls = new Payload.Call[](1);
+ vars.updateConfigPayload2.calls[0] = Payload.Call({
+ to: address(vars.wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, vars.configHash3),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ vars.updateConfigPayload2.noChainId = params.noChainId;
+ vars.updateConfigPayload2.nonce = 1;
+
+ // Sign the second payload
+ (uint256 v2, bytes32 r2, bytes32 s2) = vm.sign(params.pk2, Payload.hashFor(vars.updateConfigPayload2, vars.wallet));
+
+ // Call second update
+ vars.updateConfigSignature2 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config2,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2), ":hash:", vm.toString(r2), ":", vm.toString(s2), ":", vm.toString(v2)
+ )
+ ),
+ !params.noChainId
+ );
+
+ // Pack second payload
+ vars.updateConfigPackedPayload2 = PrimitivesRPC.toPackedPayload(vm, vars.updateConfigPayload2);
+
+ // Execute second update
+ vm.expectEmit(true, true, false, true, vars.wallet);
+ emit ImageHashUpdated(vars.configHash3);
+ Stage1Module(vars.wallet).execute(vars.updateConfigPackedPayload2, vars.updateConfigSignature2);
+
+ // Verify second update worked
+ assertEq(Stage2Module(vars.wallet).imageHash(), vars.configHash3);
+ }
+
+ struct test_update_image_hash_then_zero_params {
+ uint16 threshold1;
+ uint56 checkpoint1;
+ uint8 weight1;
+ uint256 pk1;
+ uint16 threshold2;
+ uint56 checkpoint2;
+ uint8 weight2;
+ uint256 pk2;
+ bool noChainId;
+ }
+
+ struct test_update_image_hash_then_zero_vars {
+ address signer1;
+ address signer2;
+ string config1;
+ string config2;
+ bytes32 configHash1;
+ bytes32 configHash2;
+ address payable wallet;
+ Payload.Decoded updateConfigPayload1;
+ Payload.Decoded updateConfigPayload2;
+ bytes updateConfigSignature1;
+ bytes updateConfigSignature2;
+ bytes updateConfigPackedPayload1;
+ bytes updateConfigPackedPayload2;
+ }
+
+ function test_update_image_hash_then_zero(
+ test_update_image_hash_then_zero_params memory params
+ ) external {
+ params.threshold1 = uint16(bound(params.threshold1, 0, params.weight1));
+ params.threshold2 = uint16(bound(params.threshold2, 0, params.weight2));
+ params.pk1 = boundPk(params.pk1);
+ params.pk2 = boundPk(params.pk2);
+
+ test_update_image_hash_then_zero_vars memory vars;
+ vars.signer1 = vm.addr(params.pk1);
+ vars.signer2 = vm.addr(params.pk2);
+
+ // First config
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer1), ":", vm.toString(params.weight1)));
+ vars.config1 = PrimitivesRPC.newConfig(vm, params.threshold1, params.checkpoint1, ce);
+ }
+ vars.configHash1 = PrimitivesRPC.getImageHash(vm, vars.config1);
+
+ // Deploy wallet with first config
+ vars.wallet = payable(factory.deploy(address(stage1Module), vars.configHash1));
+
+ // Second config
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer2), ":", vm.toString(params.weight2)));
+ vars.config2 = PrimitivesRPC.newConfig(vm, params.threshold2, params.checkpoint2, ce);
+ }
+ vars.configHash2 = PrimitivesRPC.getImageHash(vm, vars.config2);
+
+ // First update
+ vars.updateConfigPayload1.kind = Payload.KIND_TRANSACTIONS;
+ vars.updateConfigPayload1.calls = new Payload.Call[](1);
+ vars.updateConfigPayload1.calls[0] = Payload.Call({
+ to: address(vars.wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, vars.configHash2),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ vars.updateConfigPayload1.noChainId = params.noChainId;
+
+ // Sign the first payload
+ (uint256 v1, bytes32 r1, bytes32 s1) = vm.sign(params.pk1, Payload.hashFor(vars.updateConfigPayload1, vars.wallet));
+
+ // Call first update
+ vars.updateConfigSignature1 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config1,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1), ":hash:", vm.toString(r1), ":", vm.toString(s1), ":", vm.toString(v1)
+ )
+ ),
+ !params.noChainId
+ );
+
+ // Pack first payload
+ vars.updateConfigPackedPayload1 = PrimitivesRPC.toPackedPayload(vm, vars.updateConfigPayload1);
+
+ // Execute first update
+ vm.expectEmit(true, true, false, true, vars.wallet);
+ emit ImageHashUpdated(vars.configHash2);
+ Stage1Module(vars.wallet).execute(vars.updateConfigPackedPayload1, vars.updateConfigSignature1);
+
+ // Verify first update worked
+ assertEq(Stage1Module(vars.wallet).getImplementation(), stage1Module.STAGE_2_IMPLEMENTATION());
+ assertEq(Stage2Module(vars.wallet).imageHash(), vars.configHash2);
+
+ // Second update (attempting to set to zero)
+ vars.updateConfigPayload2.kind = Payload.KIND_TRANSACTIONS;
+ vars.updateConfigPayload2.calls = new Payload.Call[](1);
+ vars.updateConfigPayload2.calls[0] = Payload.Call({
+ to: address(vars.wallet),
+ value: 0,
+ data: abi.encodeWithSelector(BaseAuth.updateImageHash.selector, bytes32(0)),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ vars.updateConfigPayload2.noChainId = params.noChainId;
+ vars.updateConfigPayload2.nonce = 1;
+
+ // Sign the second payload
+ (uint256 v2, bytes32 r2, bytes32 s2) = vm.sign(params.pk2, Payload.hashFor(vars.updateConfigPayload2, vars.wallet));
+
+ // Call second update
+ vars.updateConfigSignature2 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config2,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2), ":hash:", vm.toString(r2), ":", vm.toString(s2), ":", vm.toString(v2)
+ )
+ ),
+ !params.noChainId
+ );
+
+ // Pack second payload
+ vars.updateConfigPackedPayload2 = PrimitivesRPC.toPackedPayload(vm, vars.updateConfigPayload2);
+
+ // Attempt second update and expect revert
+ bytes memory innerRevert = abi.encodeWithSelector(Stage1Auth.ImageHashIsZero.selector);
+ vm.expectRevert(abi.encodeWithSelector(Calls.Reverted.selector, vars.updateConfigPayload2, 0, innerRevert));
+ Stage1Module(vars.wallet).execute(vars.updateConfigPackedPayload2, vars.updateConfigSignature2);
+
+ // Verify imageHash is still configHash2
+ assertEq(Stage2Module(vars.wallet).imageHash(), vars.configHash2);
+ }
+
+ struct nested_sapient_test_params {
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ uint256 pk;
+ address parentWallet;
+ }
+
+ struct nested_sapient_test_vars {
+ address signer;
+ string config;
+ bytes32 configHash;
+ address wallet;
+ bytes parentedSignature;
+ }
+
+ function test_recover_sapient_as_if_nested(
+ nested_sapient_test_params memory params
+ ) public {
+ boundToLegalPayload(params.payload);
+ params.threshold = uint16(bound(params.threshold, 0, params.weight));
+ params.pk = boundPk(params.pk);
+
+ nested_sapient_test_vars memory vars;
+
+ vars.signer = vm.addr(params.pk);
+
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer), ":", vm.toString(params.weight)));
+ vars.config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+ vars.configHash = PrimitivesRPC.getImageHash(vm, vars.config);
+
+ vars.wallet = payable(factory.deploy(address(stage1Module), vars.configHash));
+
+ address[] memory nextParentWallets = new address[](params.payload.parentWallets.length + 1);
+ for (uint256 i = 0; i < params.payload.parentWallets.length; i++) {
+ nextParentWallets[i] = params.payload.parentWallets[i];
+ }
+ nextParentWallets[params.payload.parentWallets.length] = params.parentWallet;
+
+ address[] memory prevParentWallets = params.payload.parentWallets;
+ params.payload.parentWallets = nextParentWallets;
+
+ // Sign the parented payload
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(params.pk, Payload.hashFor(params.payload, vars.wallet));
+ vars.parentedSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config,
+ string(
+ abi.encodePacked(vm.toString(vars.signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ ),
+ !params.payload.noChainId
+ );
+
+ // Restore the original parentWallets
+ params.payload.parentWallets = prevParentWallets;
+
+ // Recover the parented payload
+ vm.prank(params.parentWallet);
+ bytes32 recovered = Stage1Auth(vars.wallet).recoverSapientSignature(params.payload, vars.parentedSignature);
+ assertEq(recovered, bytes32(uint256(1)));
+ }
+
+ function test_recover_sapient_as_if_nested_wrong_signature_fail(
+ nested_sapient_test_params memory params,
+ uint56 _differentCheckpoint
+ ) public {
+ vm.assume(_differentCheckpoint != params.checkpoint);
+ boundToLegalPayload(params.payload);
+ params.threshold = uint16(bound(params.threshold, 0, params.weight));
+ params.pk = boundPk(params.pk);
+
+ nested_sapient_test_vars memory vars;
+
+ vars.signer = vm.addr(params.pk);
+
+ string memory differentCheckpointConfig;
+ {
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(vars.signer), ":", vm.toString(params.weight)));
+ vars.config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ differentCheckpointConfig = PrimitivesRPC.newConfig(vm, params.threshold, _differentCheckpoint, ce);
+ }
+ vars.configHash = PrimitivesRPC.getImageHash(vm, vars.config);
+
+ vars.wallet = payable(factory.deploy(address(stage1Module), vars.configHash));
+
+ address[] memory nextParentWallets = new address[](params.payload.parentWallets.length + 1);
+ for (uint256 i = 0; i < params.payload.parentWallets.length; i++) {
+ nextParentWallets[i] = params.payload.parentWallets[i];
+ }
+ nextParentWallets[params.payload.parentWallets.length] = params.parentWallet;
+
+ address[] memory prevParentWallets = params.payload.parentWallets;
+ params.payload.parentWallets = nextParentWallets;
+
+ // Sign the parented payload
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(params.pk, Payload.hashFor(params.payload, vars.wallet));
+ vars.parentedSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ differentCheckpointConfig,
+ string(
+ abi.encodePacked(vm.toString(vars.signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ ),
+ !params.payload.noChainId
+ );
+
+ vm.expectRevert(
+ abi.encodeWithSelector(BaseAuth.InvalidSapientSignature.selector, params.payload, vars.parentedSignature)
+ );
+
+ // Restore the original parentWallets
+ params.payload.parentWallets = prevParentWallets;
+
+ // Recover the parented payload
+ vm.prank(params.parentWallet);
+ Stage1Auth(vars.wallet).recoverSapientSignature(params.payload, vars.parentedSignature);
+ }
+
+ function test_forbid_reentrancy(
+ uint16 _threshold,
+ uint56 _checkpoint,
+ uint8 _weight,
+ uint256 _signerPk,
+ Payload.Decoded memory _innerPayload,
+ bool _outerNoChainId,
+ bool _innerNoChainId
+ ) external {
+ CanReenter canReenter = new CanReenter();
+ _weight = uint8(bound(_weight, 0, 255));
+ _threshold = uint16(bound(_threshold, 0, _weight));
+ _checkpoint = uint56(bound(_checkpoint, 0, type(uint56).max));
+ _signerPk = boundPk(_signerPk);
+
+ address signer = vm.addr(_signerPk);
+
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(signer), ":", vm.toString(_weight)));
+ string memory config = PrimitivesRPC.newConfig(vm, _threshold, _checkpoint, ce);
+
+ address payable wallet = payable(factory.deploy(address(stage1Module), PrimitivesRPC.getImageHash(vm, config)));
+
+ // Build the inner payload
+ _innerPayload.noChainId = _innerNoChainId;
+ _innerPayload.kind = Payload.KIND_TRANSACTIONS;
+ boundToLegalPayload(_innerPayload);
+
+ // Sign the inner payload
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(_signerPk, Payload.hashFor(_innerPayload, address(wallet)));
+ bytes memory innerSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(abi.encodePacked(vm.toString(signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))),
+ !_innerNoChainId
+ );
+
+ // Pack the inner payload
+ bytes memory innerPackedPayload = PrimitivesRPC.toPackedPayload(vm, _innerPayload);
+
+ // Build the outer payload
+ Payload.Decoded memory outerPayload;
+ outerPayload.kind = Payload.KIND_TRANSACTIONS;
+ outerPayload.calls = new Payload.Call[](1);
+ outerPayload.calls[0] = Payload.Call({
+ to: address(canReenter),
+ value: 0,
+ data: abi.encodeWithSelector(
+ CanReenter.doAnotherCall.selector,
+ address(wallet),
+ abi.encodeWithSelector(Stage1Module(wallet).execute.selector, innerPackedPayload, innerSignature)
+ ),
+ gasLimit: 1000000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ outerPayload.noChainId = _outerNoChainId;
+
+ // Sign the outer payload
+ (v, r, s) = vm.sign(_signerPk, Payload.hashFor(outerPayload, address(wallet)));
+ bytes memory outerSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(abi.encodePacked(vm.toString(signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))),
+ !_outerNoChainId
+ );
+
+ // Pack the outer payload
+ bytes memory outerPackedPayload = PrimitivesRPC.toPackedPayload(vm, outerPayload);
+
+ // Execute the outer payload
+ vm.expectRevert();
+ Stage1Module(wallet).execute(outerPackedPayload, outerSignature);
+ }
+
+ function test_send_many_transactions(
+ uint256 _pk,
+ uint8 _weight,
+ uint16 _threshold,
+ uint256 _checkpoint,
+ uint256 _transactionCount,
+ bool _noChainId
+ ) external {
+ _pk = boundPk(_pk);
+ _weight = uint8(bound(_weight, 0, 255));
+ _threshold = uint16(bound(_threshold, 0, _weight));
+ _checkpoint = uint56(bound(_checkpoint, 0, type(uint56).max));
+ _transactionCount = uint256(bound(_transactionCount, 2, 10));
+
+ address signer = vm.addr(_pk);
+
+ string memory ce;
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(signer), ":", vm.toString(_weight)));
+ string memory config = PrimitivesRPC.newConfig(vm, _threshold, _checkpoint, ce);
+
+ address payable wallet = payable(factory.deploy(address(stage1Module), PrimitivesRPC.getImageHash(vm, config)));
+
+ // Send (i + 1) wei amount of ETH to address(100 + i)
+ vm.deal(wallet, 1 ether);
+
+ for (uint256 i = 0; i < _transactionCount; i++) {
+ // Construct the payload
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_TRANSACTIONS;
+ payload.calls = new Payload.Call[](1);
+ payload.calls[0] = Payload.Call({
+ to: address(uint160(100 + i)),
+ value: i + 1,
+ data: bytes(""),
+ gasLimit: 100000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ payload.noChainId = _noChainId;
+ payload.nonce = i;
+
+ // Sign the payload
+ (uint256 v, bytes32 r, bytes32 s) = vm.sign(_pk, Payload.hashFor(payload, address(wallet)));
+ bytes memory signature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(
+ abi.encodePacked(vm.toString(signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ ),
+ !_noChainId
+ );
+
+ // Pack the payload
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, payload);
+
+ // Execute the payload
+ (bool success,) = wallet.call{ value: i + 1 }(
+ abi.encodeWithSelector(Stage1Module(wallet).execute.selector, packedPayload, signature)
+ );
+ assertTrue(success);
+
+ // Verify the balance of address(100 + i)
+ assertEq(address(uint160(100 + i)).balance, i + 1);
+ }
+ }
+
+ receive() external payable { }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/Wallet.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/Wallet.t.sol
new file mode 100644
index 000000000..5af650ab0
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/Wallet.t.sol
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Factory } from "../src/Factory.sol";
+import { AdvTest } from "./utils/TestUtils.sol";
+
+contract VariableDataStore {
+
+ bytes public data;
+
+ constructor(
+ bytes memory _data
+ ) {
+ data = _data;
+ }
+
+}
+
+contract ModuleImp {
+
+ VariableDataStore public immutable expectedDataPointer;
+ VariableDataStore public immutable willReturnPointer;
+ uint256 public immutable expectedValue;
+ bool public immutable alwaysReverts;
+
+ constructor(bytes memory _expectedData, bytes memory _willReturn, uint256 _expectedValue, bool _alwaysReverts) {
+ expectedDataPointer = new VariableDataStore(_expectedData);
+ willReturnPointer = new VariableDataStore(_willReturn);
+ expectedValue = _expectedValue;
+ alwaysReverts = _alwaysReverts;
+ }
+
+ receive() external payable {
+ _verifyAndReturn();
+ }
+
+ fallback() external payable {
+ _verifyAndReturn();
+ }
+
+ function _verifyAndReturn() internal {
+ if (alwaysReverts) {
+ revert("Always reverts");
+ }
+
+ bytes memory expectedData = expectedDataPointer.data();
+ bytes memory willReturn = willReturnPointer.data();
+
+ if (keccak256(expectedData) != keccak256(msg.data)) {
+ revert("Invalid data");
+ }
+
+ if (msg.value != expectedValue) {
+ revert("Invalid value");
+ }
+
+ assembly {
+ return(add(willReturn, 32), mload(willReturn))
+ }
+ }
+
+}
+
+contract WalletTest is AdvTest {
+
+ Factory public factory;
+
+ function setUp() public {
+ factory = new Factory();
+ }
+
+ function test_forward(bytes32 _salt, bytes calldata _data, bytes calldata _return) external {
+ ModuleImp module = new ModuleImp(_data, _return, 0, false);
+ address wallet = factory.deploy(address(module), _salt);
+
+ (bool success, bytes memory returnData) = wallet.call(_data);
+ assertEq(success, true);
+ assertEq(returnData, _return);
+ }
+
+ function test_doNotForwardWithValue(bytes32 _salt, uint256 _value) external {
+ vm.assume(_value > 0);
+
+ vm.deal(address(this), _value);
+ ModuleImp module = new ModuleImp(bytes(""), bytes(""), 0, true);
+ address wallet = factory.deploy(address(module), _salt);
+
+ (bool success, bytes memory returnData) = wallet.call{ value: _value }(bytes(""));
+ assertEq(success, true);
+ assertEq(returnData, bytes(""));
+ }
+
+ function test_forwardValueWithData(
+ bytes32 _salt,
+ bytes calldata _data,
+ bytes calldata _return,
+ uint256 _value
+ ) external {
+ vm.assume(_data.length > 0);
+
+ vm.deal(address(this), _value);
+ ModuleImp module = new ModuleImp(_data, _return, _value, false);
+ address wallet = factory.deploy(address(module), _salt);
+
+ (bool success, bytes memory returnData) = wallet.call{ value: _value }(_data);
+ assertEq(success, true);
+ assertEq(returnData, _return);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/passkeys/Passkeys.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/passkeys/Passkeys.t.sol
new file mode 100644
index 000000000..8e0199d97
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/passkeys/Passkeys.t.sol
@@ -0,0 +1,540 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Test, Vm } from "forge-std/Test.sol";
+import { console } from "forge-std/console.sol";
+
+import { Passkeys } from "../../../src/extensions/passkeys/Passkeys.sol";
+import { WebAuthn } from "../../../src/utils/WebAuthn.sol";
+import { PrimitivesRPC } from "../../utils/PrimitivesRPC.sol";
+import { AdvTest } from "../../utils/TestUtils.sol";
+
+// Harness contract to expose internal functions for testing
+contract PasskeysImp is Passkeys {
+
+ function rootForPasskeyPub(
+ bool _requireUserVerification,
+ bytes32 _x,
+ bytes32 _y,
+ bytes32 _metadata
+ ) external pure returns (bytes32) {
+ return _rootForPasskey(_requireUserVerification, _x, _y, _metadata);
+ }
+
+ function decodeSignaturePub(
+ bytes calldata _signature
+ )
+ external
+ pure
+ returns (
+ WebAuthn.WebAuthnAuth memory _webAuthnAuth,
+ bool _requireUserVerification,
+ bytes32 _x,
+ bytes32 _y,
+ bytes32 _metadata
+ )
+ {
+ return _decodeSignature(_signature);
+ }
+
+}
+
+address constant P256_VERIFIER = 0x000000000000D01eA45F9eFD5c54f037Fa57Ea1a;
+bytes constant P256_VERIFIER_RUNTIME_CODE =
+ hex"3d604052610216565b60008060006ffffffffeffffffffffffffffffffffff60601b19808687098188890982838389096004098384858485093d510985868b8c096003090891508384828308850385848509089650838485858609600809850385868a880385088509089550505050808188880960020991505093509350939050565b81513d83015160408401516ffffffffeffffffffffffffffffffffff60601b19808384098183840982838388096004098384858485093d510985868a8b096003090896508384828308850385898a09089150610102848587890960020985868787880960080987038788878a0387088c0908848b523d8b015260408a0152565b505050505050505050565b81513d830151604084015185513d87015160408801518361013d578287523d870182905260408701819052610102565b80610157578587523d870185905260408701849052610102565b6ffffffffeffffffffffffffffffffffff60601b19808586098183840982818a099850828385830989099750508188830383838809089450818783038384898509870908935050826101be57836101be576101b28a89610082565b50505050505050505050565b808485098181860982828a09985082838a8b0884038483860386898a09080891506102088384868a0988098485848c09860386878789038f088a0908848d523d8d015260408c0152565b505050505050505050505050565b6020357fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325513d6040357f7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a88111156102695782035b60206108005260206108205260206108405280610860526002830361088052826108a0526ffffffffeffffffffffffffffffffffff60601b198060031860205260603560803560203d60c061080060055afa60203d1416837f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b8585873d5189898a09080908848384091484831085851016888710871510898b108b151016609f3611161616166103195760206080f35b60809182523d820152600160c08190527f6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2966102009081527f4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f53d909101526102405261038992509050610100610082565b610397610200610400610082565b6103a7610100608061018061010d565b6103b7610200608061028061010d565b6103c861020061010061030061010d565b6103d961020061018061038061010d565b6103e9610400608061048061010d565b6103fa61040061010061050061010d565b61040b61040061018061058061010d565b61041c61040061020061060061010d565b61042c610600608061068061010d565b61043d61060061010061070061010d565b61044e61060061018061078061010d565b81815182350982825185098283846ffffffffeffffffffffffffffffffffff60601b193d515b82156105245781858609828485098384838809600409848586848509860986878a8b096003090885868384088703878384090886878887880960080988038889848b03870885090887888a8d096002098882830996508881820995508889888509600409945088898a8889098a098a8b86870960030908935088898687088a038a868709089a5088898284096002099950505050858687868709600809870387888b8a0386088409089850505050505b61018086891b60f71c16610600888a1b60f51c16176040810151801585151715610564578061055357506105fe565b81513d8301519750955093506105fe565b83858609848283098581890986878584098b0991508681880388858851090887838903898a8c88093d8a015109089350836105b957806105b9576105a9898c8c610008565b9a509b50995050505050506105fe565b8781820988818309898285099350898a8586088b038b838d038d8a8b0908089b50898a8287098b038b8c8f8e0388088909089c5050508788868b098209985050505050505b5082156106af5781858609828485098384838809600409848586848509860986878a8b096003090885868384088703878384090886878887880960080988038889848b03870885090887888a8d096002098882830996508881820995508889888509600409945088898a8889098a098a8b86870960030908935088898687088a038a868709089a5088898284096002099950505050858687868709600809870387888b8a0386088409089850505050505b61018086891b60f51c16610600888a1b60f31c161760408101518015851517156106ef57806106de5750610789565b81513d830151975095509350610789565b83858609848283098581890986878584098b0991508681880388858851090887838903898a8c88093d8a01510908935083610744578061074457610734898c8c610008565b9a509b5099505050505050610789565b8781820988818309898285099350898a8586088b038b838d038d8a8b0908089b50898a8287098b038b8c8f8e0388088909089c5050508788868b098209985050505050505b50600488019760fb19016104745750816107a2573d6040f35b81610860526002810361088052806108a0523d3d60c061080060055afa898983843d513d510987090614163d525050505050505050503d3df3fea264697066735822122063ce32ec0e56e7893a1f6101795ce2e38aca14dd12adb703c71fe3bee27da71e64736f6c634300081a0033";
+
+contract PasskeysTest is AdvTest {
+
+ PasskeysImp public passkeysImp;
+
+ function setUp() public {
+ passkeysImp = new PasskeysImp();
+ }
+
+ // --- _rootForPasskey Tests ---
+
+ // Fuzz test for _rootForPasskey using metadataHash
+ function test_rootForPasskey_metadataHash(
+ bool requireUserVerification,
+ bytes32 x,
+ bytes32 y,
+ bytes32 metadataHash
+ ) public {
+ bytes32 contractRoot = passkeysImp.rootForPasskeyPub(requireUserVerification, x, y, metadataHash);
+
+ PrimitivesRPC.PasskeyPublicKey memory pkParams;
+ pkParams.x = x;
+ pkParams.y = y;
+ pkParams.requireUserVerification = requireUserVerification;
+ pkParams.metadataHash = metadataHash;
+
+ bytes32 rpcRoot = PrimitivesRPC.passkeysComputeRoot(vm, pkParams);
+
+ assertEq(contractRoot, rpcRoot, "Contract root hash should match RPC root hash using metadataHash");
+ }
+
+ // Fuzz test for _rootForPasskey using credentialId
+ function test_rootForPasskey_credentialId(
+ bool requireUserVerification,
+ bytes32 x,
+ bytes32 y,
+ uint256 credentialIdSeed
+ ) public {
+ string memory credentialId = generateRandomString(credentialIdSeed);
+ vm.assume(bytes(credentialId).length > 0);
+ bytes32 expectedMetadataNodeHash = keccak256(bytes(credentialId));
+ bytes32 contractRoot = passkeysImp.rootForPasskeyPub(requireUserVerification, x, y, expectedMetadataNodeHash);
+
+ PrimitivesRPC.PasskeyPublicKey memory pkParams;
+ pkParams.x = x;
+ pkParams.y = y;
+ pkParams.requireUserVerification = requireUserVerification;
+ pkParams.credentialId = credentialId;
+
+ bytes32 rpcRoot = PrimitivesRPC.passkeysComputeRoot(vm, pkParams);
+
+ assertEq(contractRoot, rpcRoot, "Contract root hash should match RPC root hash using credentialId");
+ }
+
+ // Fuzz test for _rootForPasskey without metadata
+ function test_rootForPasskey_noMetadata(bool requireUserVerification, bytes32 x, bytes32 y) public {
+ bytes32 noMetadataHash = bytes32(0);
+ bytes32 contractRoot = passkeysImp.rootForPasskeyPub(requireUserVerification, x, y, noMetadataHash);
+
+ PrimitivesRPC.PasskeyPublicKey memory pkParams;
+ pkParams.x = x;
+ pkParams.y = y;
+ pkParams.requireUserVerification = requireUserVerification;
+
+ bytes32 rpcRoot = PrimitivesRPC.passkeysComputeRoot(vm, pkParams);
+
+ assertEq(contractRoot, rpcRoot, "Contract root hash should match RPC root hash without metadata");
+ }
+
+ struct test_decodeSignature_packed_params {
+ bool requireUserVerification;
+ bytes32 x;
+ bytes32 y;
+ bytes32 r;
+ bytes32 s;
+ bytes authenticatorData;
+ bytes challengeBytes;
+ bytes32 metadataHash;
+ bool embedMetadata;
+ uint256 typeValueSeed;
+ uint256 originValueSeed;
+ }
+
+ struct test_decodeSignature_packed_vars {
+ string clientDataJSON;
+ uint256 challengeIndex;
+ uint256 typeIndex;
+ PrimitivesRPC.PasskeyPublicKey pkParams;
+ PrimitivesRPC.PasskeySignatureComponents sigParams;
+ bytes encodedSignature;
+ WebAuthn.WebAuthnAuth decodedAuth;
+ bool decodedRUV;
+ bytes32 decodedX;
+ bytes32 decodedY;
+ bytes32 decodedMetadata;
+ string typeValue;
+ string originValue;
+ }
+
+ function test_decodeSignature_packed(
+ test_decodeSignature_packed_params memory params
+ ) public {
+ vm.assume(params.authenticatorData.length > 0 && params.authenticatorData.length <= 65535);
+ vm.assume(params.challengeBytes.length > 0 && params.challengeBytes.length < 100);
+ vm.assume(params.r != bytes32(0));
+ vm.assume(params.s != bytes32(0));
+
+ if (params.embedMetadata) {
+ vm.assume(params.metadataHash != bytes32(0));
+ } else {
+ params.metadataHash = bytes32(0);
+ }
+
+ test_decodeSignature_packed_vars memory vars;
+
+ string memory base64UrlChallenge = vm.toBase64URL(params.challengeBytes);
+
+ vars.typeValue = generateRandomString(params.typeValueSeed);
+ vars.originValue = generateRandomString(params.originValueSeed);
+
+ vars.clientDataJSON = string.concat(
+ '{"type":"', vars.typeValue, '","challenge":"', base64UrlChallenge, '","origin":"', vars.originValue, '"}'
+ );
+
+ vars.typeIndex = 1;
+ vars.challengeIndex = 11 + bytes(vars.typeValue).length;
+
+ vars.pkParams.x = params.x;
+ vars.pkParams.y = params.y;
+ vars.pkParams.requireUserVerification = params.requireUserVerification;
+ if (params.embedMetadata || params.metadataHash != bytes32(0)) {
+ vars.pkParams.metadataHash = params.metadataHash;
+ }
+
+ vars.sigParams.r = params.r;
+ vars.sigParams.s = params.s;
+ vars.sigParams.authenticatorData = params.authenticatorData;
+ vars.sigParams.clientDataJson = vars.clientDataJSON;
+
+ vars.encodedSignature =
+ PrimitivesRPC.passkeysEncodeSignature(vm, vars.pkParams, vars.sigParams, params.embedMetadata);
+
+ (vars.decodedAuth, vars.decodedRUV, vars.decodedX, vars.decodedY, vars.decodedMetadata) =
+ passkeysImp.decodeSignaturePub(vars.encodedSignature);
+
+ assertEq(vars.decodedRUV, params.requireUserVerification, "Packed Decoded RUV mismatch");
+ assertEq(vars.decodedY, params.y, "Packed Decoded Y mismatch");
+ assertEq(vars.decodedX, params.x, "Packed Decoded X mismatch");
+ assertEq(
+ keccak256(vars.decodedAuth.authenticatorData),
+ keccak256(params.authenticatorData),
+ "Packed Decoded authenticatorData mismatch"
+ );
+ assertEq(
+ keccak256(bytes(vars.decodedAuth.clientDataJSON)),
+ keccak256(bytes(vars.clientDataJSON)),
+ "Packed Decoded clientDataJSON mismatch"
+ );
+ assertEq(vars.decodedAuth.r, params.r, "Packed Decoded R mismatch");
+ assertEq(vars.decodedAuth.s, params.s, "Packed Decoded S mismatch");
+ assertEq(vars.decodedAuth.challengeIndex, vars.challengeIndex, "Packed Decoded challengeIndex mismatch");
+ assertEq(vars.decodedAuth.typeIndex, vars.typeIndex, "Packed Decoded typeIndex mismatch");
+ assertEq(vars.decodedMetadata, params.metadataHash, "Packed Decoded metadata mismatch");
+ }
+
+ struct test_decodeSignature_abi_params {
+ bool requireUserVerification;
+ bytes32 x;
+ bytes32 y;
+ bytes32 r;
+ bytes32 s;
+ bytes authenticatorData;
+ bytes challengeBytes;
+ bytes32 metadataHash;
+ bool includeMetadata;
+ uint256 typeValueSeed;
+ uint256 originValueSeed;
+ }
+
+ struct test_decodeSignature_abi_vars {
+ string clientDataJSON;
+ uint256 challengeIndex;
+ uint256 typeIndex;
+ WebAuthn.WebAuthnAuth authInput;
+ bytes encodedTuple;
+ bytes1 flagByte;
+ bytes encodedSignatureWithFlag;
+ WebAuthn.WebAuthnAuth decodedAuth;
+ bool decodedRUV;
+ bytes32 decodedX;
+ bytes32 decodedY;
+ bytes32 decodedMetadata;
+ string typeValue;
+ string originValue;
+ }
+
+ // Fuzz test for _decodeSignature using the ABI encoded fallback format
+ function test_decodeSignature_abi(
+ test_decodeSignature_abi_params memory params
+ ) public view {
+ // --- Setup & Assumptions ---
+ vm.assume(params.authenticatorData.length > 0 && params.authenticatorData.length <= 65535);
+ vm.assume(params.challengeBytes.length > 0 && params.challengeBytes.length < 100);
+ vm.assume(params.r != bytes32(0));
+ vm.assume(params.s != bytes32(0));
+
+ if (params.includeMetadata) {
+ vm.assume(params.metadataHash != bytes32(0));
+ } else {
+ params.metadataHash = bytes32(0);
+ }
+
+ test_decodeSignature_abi_vars memory vars;
+
+ string memory base64UrlChallenge = vm.toBase64URL(params.challengeBytes);
+ vars.typeValue = generateRandomString(params.typeValueSeed);
+ vars.originValue = generateRandomString(params.originValueSeed);
+
+ vars.clientDataJSON = string.concat(
+ '{"type":"', vars.typeValue, '","challenge":"', base64UrlChallenge, '","origin":"', vars.originValue, '"}'
+ );
+ vars.challengeIndex = 11 + bytes(vars.typeValue).length;
+ vars.typeIndex = 1;
+
+ // --- ABI Encoding ---
+ vars.authInput = WebAuthn.WebAuthnAuth({
+ authenticatorData: params.authenticatorData,
+ clientDataJSON: vars.clientDataJSON,
+ challengeIndex: vars.challengeIndex,
+ typeIndex: vars.typeIndex,
+ r: params.r,
+ s: params.s
+ });
+
+ vars.encodedTuple =
+ abi.encode(vars.authInput, params.requireUserVerification, params.x, params.y, params.metadataHash);
+ vars.flagByte = bytes1(uint8(0x20) | (params.includeMetadata ? uint8(0x40) : uint8(0x00)));
+ vars.encodedSignatureWithFlag = abi.encodePacked(vars.flagByte, vars.encodedTuple);
+
+ // --- Contract Decoding ---
+ (vars.decodedAuth, vars.decodedRUV, vars.decodedX, vars.decodedY, vars.decodedMetadata) =
+ passkeysImp.decodeSignaturePub(vars.encodedSignatureWithFlag);
+
+ // --- Assertions ---
+ assertEq(vars.decodedRUV, params.requireUserVerification, "ABI Decoded RUV mismatch");
+ assertEq(vars.decodedX, params.x, "ABI Decoded X mismatch");
+ assertEq(vars.decodedY, params.y, "ABI Decoded Y mismatch");
+ assertEq(
+ keccak256(vars.decodedAuth.authenticatorData),
+ keccak256(params.authenticatorData),
+ "ABI Decoded authenticatorData mismatch"
+ );
+ assertEq(
+ keccak256(bytes(vars.decodedAuth.clientDataJSON)),
+ keccak256(bytes(vars.clientDataJSON)),
+ "ABI Decoded clientDataJSON mismatch"
+ );
+ assertEq(vars.decodedAuth.r, params.r, "ABI Decoded R mismatch");
+ assertEq(vars.decodedAuth.s, params.s, "ABI Decoded S mismatch");
+ assertEq(vars.decodedAuth.challengeIndex, vars.challengeIndex, "ABI Decoded challengeIndex mismatch");
+ assertEq(vars.decodedAuth.typeIndex, vars.typeIndex, "ABI Decoded typeIndex mismatch");
+ assertEq(vars.decodedMetadata, params.metadataHash, "ABI Decoded metadata mismatch");
+ }
+
+ struct RecoverParams {
+ uint256 pkSeed;
+ bytes32 digest;
+ bool requireUserVerification;
+ bytes32 metadataHash;
+ bool embedMetadata;
+ uint256 originValueSeed;
+ bytes32 rpIdHash;
+ uint32 signCount;
+ }
+
+ struct recoverSapientSignatureCompact_valid_vars {
+ Vm.Wallet wallet;
+ uint256 pubX;
+ uint256 pubY;
+ PrimitivesRPC.PasskeyPublicKey pkParams;
+ string base64UrlChallenge;
+ string typeValue;
+ string originValue;
+ string clientDataJSON;
+ PrimitivesRPC.PasskeySignatureComponents sigParams;
+ bytes32 clientDataJSONHash;
+ bytes32 messageHash;
+ bytes encodedSignature;
+ bytes32 expectedRoot;
+ bytes32 recoveredRoot;
+ bytes generatedAuthenticatorData;
+ }
+
+ function test_recoverSapientSignatureCompact_valid(
+ RecoverParams memory params
+ ) public {
+ vm.etch(P256_VERIFIER, P256_VERIFIER_RUNTIME_CODE);
+
+ recoverSapientSignatureCompact_valid_vars memory vars;
+
+ params.pkSeed = boundP256Pk(params.pkSeed);
+ vars.wallet = vm.createWallet(params.pkSeed);
+
+ if (params.embedMetadata) {
+ vm.assume(params.metadataHash != bytes32(0));
+ } else {
+ params.metadataHash = bytes32(0);
+ }
+
+ (vars.pubX, vars.pubY) = vm.publicKeyP256(vars.wallet.privateKey);
+ vars.pkParams.x = bytes32(vars.pubX);
+ vars.pkParams.y = bytes32(vars.pubY);
+ vars.pkParams.requireUserVerification = params.requireUserVerification;
+ vars.pkParams.metadataHash = params.metadataHash;
+ vars.pkParams.credentialId = "";
+
+ uint8 flags = 0x01;
+ if (params.requireUserVerification) {
+ flags |= 0x04;
+ }
+
+ vars.generatedAuthenticatorData = abi.encodePacked(params.rpIdHash, flags, params.signCount);
+
+ string memory raw = vm.toBase64URL(abi.encodePacked(params.digest));
+ if (bytes(raw)[bytes(raw).length - 1] == "=") {
+ assembly {
+ mstore(raw, sub(mload(raw), 1))
+ }
+ }
+ vars.base64UrlChallenge = raw;
+ vars.typeValue = "webauthn.get";
+ vars.originValue = generateRandomString(params.originValueSeed);
+ vm.assume(bytes(vars.originValue).length > 0);
+
+ vars.clientDataJSON = string.concat(
+ '{"type":"', vars.typeValue, '","challenge":"', vars.base64UrlChallenge, '","origin":"', vars.originValue, '"}'
+ );
+ vars.sigParams.clientDataJson = vars.clientDataJSON;
+ vars.sigParams.authenticatorData = vars.generatedAuthenticatorData;
+
+ vars.clientDataJSONHash = sha256(bytes(vars.clientDataJSON));
+ vars.messageHash = sha256(abi.encodePacked(vars.generatedAuthenticatorData, vars.clientDataJSONHash));
+ (bytes32 rVal, bytes32 sVal) = vm.signP256(vars.wallet.privateKey, vars.messageHash);
+
+ bytes32 halfN = bytes32(0x7fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8);
+ if (sVal > halfN) {
+ sVal = bytes32(0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 - uint256(sVal));
+ }
+
+ vars.sigParams.r = bytes32(rVal);
+ vars.sigParams.s = bytes32(sVal);
+ vars.encodedSignature =
+ PrimitivesRPC.passkeysEncodeSignature(vm, vars.pkParams, vars.sigParams, params.embedMetadata);
+
+ vars.expectedRoot = PrimitivesRPC.passkeysComputeRoot(vm, vars.pkParams);
+
+ vars.recoveredRoot = passkeysImp.recoverSapientSignatureCompact(params.digest, vars.encodedSignature);
+ assertEq(vars.recoveredRoot, vars.expectedRoot, "Recovered root should match expected root");
+ }
+
+ struct recoverSapientSignatureCompact_invalidSignature_vars {
+ Vm.Wallet wallet;
+ Vm.Wallet wrongWallet;
+ uint256 pubX;
+ uint256 pubY;
+ PrimitivesRPC.PasskeyPublicKey pkParams;
+ string base64UrlChallenge;
+ string typeValue;
+ string originValue;
+ string clientDataJSON;
+ PrimitivesRPC.PasskeySignatureComponents sigParams;
+ bytes32 clientDataJSONHash;
+ bytes32 messageHash;
+ bytes encodedSignature;
+ uint256 challengeIndex;
+ uint256 typeIndex;
+ WebAuthn.WebAuthnAuth expectedAuthStruct;
+ bytes generatedAuthenticatorData;
+ }
+
+ function test_recoverSapientSignatureCompact_invalidSignature(RecoverParams memory params, uint256 wrongSeed) public {
+ vm.etch(P256_VERIFIER, P256_VERIFIER_RUNTIME_CODE);
+
+ recoverSapientSignatureCompact_invalidSignature_vars memory vars;
+
+ params.pkSeed = boundP256Pk(params.pkSeed);
+ wrongSeed = boundP256Pk(wrongSeed);
+ vm.assume(wrongSeed != params.pkSeed);
+
+ vars.wallet = vm.createWallet(params.pkSeed);
+ vars.wrongWallet = vm.createWallet(wrongSeed);
+
+ if (params.embedMetadata) {
+ vm.assume(params.metadataHash != bytes32(0));
+ } else {
+ params.metadataHash = bytes32(0);
+ }
+
+ (vars.pubX, vars.pubY) = vm.publicKeyP256(vars.wallet.privateKey);
+ vars.pkParams.x = bytes32(vars.pubX);
+ vars.pkParams.y = bytes32(vars.pubY);
+ vars.pkParams.requireUserVerification = params.requireUserVerification;
+ vars.pkParams.metadataHash = params.metadataHash;
+ vars.pkParams.credentialId = "";
+
+ uint8 flags = 0x01;
+ if (params.requireUserVerification) {
+ flags |= 0x04;
+ }
+ vars.generatedAuthenticatorData = abi.encodePacked(params.rpIdHash, flags, params.signCount);
+
+ string memory raw = vm.toBase64URL(abi.encodePacked(params.digest));
+ if (bytes(raw)[bytes(raw).length - 1] == "=") {
+ assembly {
+ mstore(raw, sub(mload(raw), 1))
+ }
+ }
+ vars.base64UrlChallenge = raw;
+ vars.typeValue = "webauthn.get";
+ vars.originValue = generateRandomString(params.originValueSeed);
+ vm.assume(bytes(vars.originValue).length > 0);
+
+ vars.clientDataJSON = string.concat(
+ '{"type":"', vars.typeValue, '","challenge":"', vars.base64UrlChallenge, '","origin":"', vars.originValue, '"}'
+ );
+ vars.sigParams.clientDataJson = vars.clientDataJSON;
+ vars.sigParams.authenticatorData = vars.generatedAuthenticatorData;
+
+ vars.clientDataJSONHash = sha256(bytes(vars.clientDataJSON));
+ vars.messageHash = sha256(abi.encodePacked(vars.generatedAuthenticatorData, vars.clientDataJSONHash));
+ (vars.sigParams.r, vars.sigParams.s) = vm.signP256(vars.wrongWallet.privateKey, vars.messageHash);
+
+ vars.encodedSignature =
+ PrimitivesRPC.passkeysEncodeSignature(vm, vars.pkParams, vars.sigParams, params.embedMetadata);
+
+ vars.challengeIndex = LibString.indexOf(vars.clientDataJSON, '"challenge":"');
+ vars.typeIndex = LibString.indexOf(vars.clientDataJSON, '"type":"');
+
+ vars.expectedAuthStruct = WebAuthn.WebAuthnAuth({
+ authenticatorData: vars.generatedAuthenticatorData,
+ clientDataJSON: vars.clientDataJSON,
+ challengeIndex: vars.challengeIndex,
+ typeIndex: vars.typeIndex,
+ r: vars.sigParams.r,
+ s: vars.sigParams.s
+ });
+
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ Passkeys.InvalidPasskeySignature.selector,
+ vars.expectedAuthStruct,
+ params.requireUserVerification,
+ vars.pkParams.x,
+ vars.pkParams.y
+ )
+ );
+ passkeysImp.recoverSapientSignatureCompact(params.digest, vars.encodedSignature);
+ }
+
+ function boundP256Pk(
+ uint256 _a
+ ) internal pure returns (uint256) {
+ _a = bound(_a, 1, 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550);
+ return _a;
+ }
+
+}
+
+library LibString {
+
+ function indexOf(string memory haystack, string memory needle) internal pure returns (uint256) {
+ bytes memory h = bytes(haystack);
+ bytes memory n = bytes(needle);
+ if (n.length == 0) {
+ return 0;
+ }
+ if (n.length > h.length) {
+ return type(uint256).max;
+ }
+
+ for (uint256 i = 0; i <= h.length - n.length; i++) {
+ bool m = true;
+ for (uint256 j = 0; j < n.length; j++) {
+ if (h[i + j] != n[j]) {
+ m = false;
+ break;
+ }
+ }
+ if (m) {
+ return i;
+ }
+ }
+ return type(uint256).max;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/recovery/Recovery.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/recovery/Recovery.t.sol
new file mode 100644
index 000000000..77037dfb9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/recovery/Recovery.t.sol
@@ -0,0 +1,595 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Recovery } from "../../../src/extensions/recovery/Recovery.sol";
+
+import { Payload } from "../../../src/modules/Payload.sol";
+import { IERC1271 } from "../../../src/modules/interfaces/IERC1271.sol";
+import { PrimitivesRPC } from "../../utils/PrimitivesRPC.sol";
+import { AdvTest } from "../../utils/TestUtils.sol";
+import { console } from "forge-std/console.sol";
+
+contract RecoveryImp is Recovery {
+
+ function recoverBranch(
+ address _wallet,
+ bytes32 _payloadHash,
+ bytes calldata _signature
+ ) external view returns (bool verified, bytes32 root) {
+ return _recoverBranch(_wallet, _payloadHash, _signature);
+ }
+
+}
+
+contract RecoveryTest is AdvTest {
+
+ RecoveryImp public recovery;
+
+ function setUp() public {
+ recovery = new RecoveryImp();
+ }
+
+ struct Signer {
+ address signer;
+ uint24 requiredDeltaTime;
+ uint64 minTimestamp;
+ }
+
+ function test_recoverBranch(Signer[] calldata signers, address wallet, bytes32 payloadHash) public {
+ vm.assume(signers.length > 0);
+
+ string memory leaves;
+
+ for (uint256 i = 0; i < signers.length; i++) {
+ if (i > 0) {
+ leaves = string.concat(leaves, " ");
+ }
+ leaves = string.concat(
+ leaves,
+ "signer:",
+ vm.toString(signers[i].signer),
+ ":",
+ vm.toString(signers[i].requiredDeltaTime),
+ ":",
+ vm.toString(signers[i].minTimestamp)
+ );
+ }
+
+ bytes32 rpcRoot = PrimitivesRPC.recoveryHashFromLeaves(vm, leaves);
+ vm.assume(rpcRoot != bytes32(0));
+
+ bytes memory encoded = PrimitivesRPC.recoveryEncode(vm, leaves);
+ bytes32 rpcRootEncoded = PrimitivesRPC.recoveryHashEncoded(vm, encoded);
+ assertEq(rpcRoot, rpcRootEncoded);
+
+ (bool verified, bytes32 root) = recovery.recoverBranch(wallet, payloadHash, encoded);
+ assertEq(verified, false);
+ assertEq(root, rpcRoot);
+ }
+
+ function test_queue_payload(
+ uint256 _signerPk,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime
+ ) external {
+ boundToLegalPayload(_payload);
+
+ vm.warp(_randomTime);
+
+ _signerPk = boundPk(_signerPk);
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+ bytes32 payloadHash = Payload.hashFor(_payload, _wallet);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPk, recoveryPayloadHash);
+
+ bytes32 yParityAndS = bytes32((uint256(v - 27) << 255) | uint256(s));
+ bytes memory signature = abi.encodePacked(r, yParityAndS);
+
+ address signerAddr = vm.addr(_signerPk);
+
+ vm.expectEmit(true, true, true, true, address(recovery));
+ emit Recovery.NewQueuedPayload(_wallet, signerAddr, payloadHash, block.timestamp);
+ recovery.queuePayload(_wallet, signerAddr, _payload, signature);
+
+ assertEq(recovery.totalQueuedPayloads(_wallet, signerAddr), 1);
+ assertEq(recovery.queuedPayloadHashes(_wallet, signerAddr, 0), payloadHash);
+ assertEq(recovery.timestampForQueuedPayload(_wallet, signerAddr, payloadHash), block.timestamp);
+ }
+
+ function test_queue_payload_ecdsa_with_code(
+ uint256 _signerPk,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime,
+ bytes memory _randomCode
+ ) external {
+ _randomCode = abi.encodePacked(bytes1(0x00), _randomCode);
+ boundToLegalPayload(_payload);
+
+ vm.warp(_randomTime);
+
+ _signerPk = boundPk(_signerPk);
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+ bytes32 payloadHash = Payload.hashFor(_payload, _wallet);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPk, recoveryPayloadHash);
+
+ bytes32 yParityAndS = bytes32((uint256(v - 27) << 255) | uint256(s));
+ bytes memory signature = abi.encodePacked(r, yParityAndS);
+
+ address signerAddr = vm.addr(_signerPk);
+ vm.etch(signerAddr, _randomCode);
+
+ vm.expectEmit(true, true, true, true, address(recovery));
+ emit Recovery.NewQueuedPayload(_wallet, signerAddr, payloadHash, block.timestamp);
+ recovery.queuePayload(_wallet, signerAddr, _payload, signature);
+
+ assertEq(recovery.totalQueuedPayloads(_wallet, signerAddr), 1);
+ assertEq(recovery.queuedPayloadHashes(_wallet, signerAddr, 0), payloadHash);
+ assertEq(recovery.timestampForQueuedPayload(_wallet, signerAddr, payloadHash), block.timestamp);
+ }
+
+ function test_queue_payload_invalid_signature_fail_no_code(
+ uint256 _signerPk,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime,
+ address _wrongSigner
+ ) external {
+ assumeNotPrecompile(_wrongSigner);
+ vm.assume(_wrongSigner.code.length == 0);
+
+ boundToLegalPayload(_payload);
+ _signerPk = boundPk(_signerPk);
+
+ address signerAddr = vm.addr(_signerPk);
+ vm.assume(signerAddr != _wrongSigner);
+ vm.label(signerAddr, "signer");
+ vm.label(_wrongSigner, "wrongSigner");
+
+ vm.warp(_randomTime);
+
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPk, recoveryPayloadHash);
+
+ bytes32 yParityAndS = bytes32((uint256(v - 27) << 255) | uint256(s));
+ bytes memory signature = abi.encodePacked(r, yParityAndS);
+
+ vm.expectRevert(
+ abi.encodeWithSelector(Recovery.InvalidSignature.selector, _wallet, _wrongSigner, _payload, signature)
+ );
+ recovery.queuePayload(_wallet, _wrongSigner, _payload, signature);
+ }
+
+ function test_queue_payload_invalid_signature_fail_has_code(
+ uint256 _signerPk,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime,
+ address _wrongSigner,
+ bytes memory _randomCode
+ ) external {
+ _wrongSigner = boundNoPrecompile(_wrongSigner);
+ assumeNotPrecompile2(_wrongSigner);
+ // Ensure there is code without 0xef prefix
+ _randomCode = abi.encodePacked(bytes1(0x00), _randomCode);
+
+ vm.etch(_wrongSigner, _randomCode);
+
+ boundToLegalPayload(_payload);
+ _signerPk = boundPk(_signerPk);
+
+ {
+ address signerAddr = vm.addr(_signerPk);
+ vm.assume(signerAddr != _wrongSigner);
+ vm.label(signerAddr, "signer");
+ vm.label(_wrongSigner, "wrongSigner");
+ }
+
+ vm.warp(_randomTime);
+
+ bytes memory signature;
+ {
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPk, recoveryPayloadHash);
+
+ bytes32 yParityAndS = bytes32((uint256(v - 27) << 255) | uint256(s));
+ signature = abi.encodePacked(r, yParityAndS);
+
+ vm.mockCall(
+ _wrongSigner,
+ abi.encodeWithSelector(IERC1271.isValidSignature.selector, recoveryPayloadHash, signature),
+ abi.encode(bytes4(0x00000000))
+ );
+ }
+
+ vm.expectRevert(
+ abi.encodeWithSelector(Recovery.InvalidSignature.selector, _wallet, _wrongSigner, _payload, signature)
+ );
+ recovery.queuePayload(_wallet, _wrongSigner, _payload, signature);
+ }
+
+ function test_queue_payload_already_queued_fail(
+ uint256 _signerPk,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint256 _randomTime,
+ uint256 _waitBetweenQueues
+ ) external {
+ boundToLegalPayload(_payload);
+ _signerPk = boundPk(_signerPk);
+
+ _randomTime = bound(_randomTime, 1, type(uint64).max);
+ _waitBetweenQueues = bound(_waitBetweenQueues, 0, type(uint64).max - _randomTime);
+
+ address signerAddr = vm.addr(_signerPk);
+ vm.warp(_randomTime);
+
+ _signerPk = boundPk(_signerPk);
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+ bytes32 payloadHash = Payload.hashFor(_payload, _wallet);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerPk, recoveryPayloadHash);
+
+ bytes32 yParityAndS = bytes32((uint256(v - 27) << 255) | uint256(s));
+ bytes memory signature = abi.encodePacked(r, yParityAndS);
+
+ recovery.queuePayload(_wallet, signerAddr, _payload, signature);
+ vm.warp(block.timestamp + _waitBetweenQueues);
+
+ vm.expectRevert(abi.encodeWithSelector(Recovery.AlreadyQueued.selector, _wallet, signerAddr, payloadHash));
+ recovery.queuePayload(_wallet, signerAddr, _payload, signature);
+ }
+
+ function test_queue_payload_erc1271(
+ address _signer,
+ bytes calldata _signature,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime,
+ bytes memory _signerCode
+ ) external {
+ boundToLegalPayload(_payload);
+ _signer = boundNoPrecompile(_signer);
+ assumeNotPrecompile2(_signer);
+
+ _signerCode = abi.encodePacked(bytes1(0x00), _signerCode);
+ vm.warp(_randomTime);
+
+ bytes32 payloadHash = Payload.hashFor(_payload, _wallet);
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+
+ vm.mockCall(
+ _signer,
+ abi.encodeWithSelector(IERC1271.isValidSignature.selector, recoveryPayloadHash, _signature),
+ abi.encode(bytes4(0x1626ba7e))
+ );
+ vm.etch(_signer, _signerCode);
+
+ vm.expectEmit(true, true, true, true, address(recovery));
+ emit Recovery.NewQueuedPayload(_wallet, _signer, payloadHash, block.timestamp);
+ recovery.queuePayload(_wallet, _signer, _payload, _signature);
+
+ assertEq(recovery.totalQueuedPayloads(_wallet, _signer), 1);
+ assertEq(recovery.queuedPayloadHashes(_wallet, _signer, 0), payloadHash);
+ assertEq(recovery.timestampForQueuedPayload(_wallet, _signer, payloadHash), block.timestamp);
+ }
+
+ function test_queue_payload_erc1271_invalid_signature_fail(
+ address _signer,
+ bytes calldata _signature,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime,
+ bytes memory _signerCode,
+ bytes4 _badMagicValue
+ ) external {
+ boundToLegalPayload(_payload);
+ _signer = boundNoPrecompile(_signer);
+ assumeNotPrecompile2(_signer);
+
+ _signerCode = abi.encodePacked(bytes1(0x00), _signerCode);
+ vm.warp(_randomTime);
+ if (_badMagicValue == bytes4(0x1626ba7e)) {
+ _badMagicValue = bytes4(0);
+ }
+
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+
+ vm.mockCall(
+ _signer,
+ abi.encodeWithSelector(IERC1271.isValidSignature.selector, recoveryPayloadHash, _signature),
+ abi.encode(_badMagicValue)
+ );
+ vm.etch(_signer, _signerCode);
+
+ vm.expectRevert(abi.encodeWithSelector(Recovery.InvalidSignature.selector, _wallet, _signer, _payload, _signature));
+ recovery.queuePayload(_wallet, _signer, _payload, _signature);
+ }
+
+ function test_queue_payload_erc1271_revert_fail(
+ address _signer,
+ bytes calldata _signature,
+ address _wallet,
+ Payload.Decoded memory _payload,
+ uint64 _randomTime,
+ bytes memory _signerCode,
+ bytes calldata _revertData
+ ) external {
+ boundToLegalPayload(_payload);
+ _signer = boundNoPrecompile(_signer);
+ assumeNotPrecompile2(_signer);
+
+ _signerCode = abi.encodePacked(bytes1(0x00), _signerCode);
+ vm.warp(_randomTime);
+
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(_wallet, _payload);
+
+ vm.mockCallRevert(
+ _signer, abi.encodeWithSelector(IERC1271.isValidSignature.selector, recoveryPayloadHash, _signature), _revertData
+ );
+ vm.etch(_signer, _signerCode);
+
+ vm.expectRevert(_revertData);
+ recovery.queuePayload(_wallet, _signer, _payload, _signature);
+ }
+
+ struct other_leaf {
+ address signer;
+ uint24 requiredDeltaTime;
+ uint64 minTimestamp;
+ }
+
+ struct test_recover_sapient_signature_compact_params {
+ uint256 signerPk;
+ address wallet;
+ Payload.Decoded payload;
+ uint256 startTime;
+ uint256 passedTime;
+ uint256 minTimestamp;
+ uint256 requiredDeltaTime;
+ other_leaf[] suffixes;
+ other_leaf[] prefixes;
+ }
+
+ struct test_recover_sapient_signature_compact_vars {
+ bytes32 recoveryPayloadHash;
+ bytes32 payloadHash;
+ uint8 v;
+ bytes32 r;
+ bytes32 s;
+ bytes32 yParityAndS;
+ bytes signature;
+ address signerAddr;
+ string parts;
+ bytes32 rpcRoot;
+ bytes encoded;
+ bytes32 recoveredRoot;
+ }
+
+ function test_recover_sapient_signature_compact(
+ test_recover_sapient_signature_compact_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+ params.startTime = bound(params.startTime, 1, type(uint64).max / 2); // Safer upper bound perhaps
+ params.requiredDeltaTime = bound(params.requiredDeltaTime, 0, type(uint24).max);
+ params.minTimestamp = bound(params.minTimestamp, 0, params.startTime);
+ uint256 minPassedTime = params.requiredDeltaTime == type(uint64).max ? type(uint64).max : params.requiredDeltaTime;
+
+ params.passedTime = bound(params.passedTime, minPassedTime, type(uint64).max);
+ vm.warp(params.startTime);
+
+ params.signerPk = boundPk(params.signerPk);
+
+ test_recover_sapient_signature_compact_vars memory vars;
+ vars.recoveryPayloadHash = recovery.recoveryPayloadHash(params.wallet, params.payload);
+ vars.payloadHash = Payload.hashFor(params.payload, params.wallet);
+ (vars.v, vars.r, vars.s) = vm.sign(params.signerPk, vars.recoveryPayloadHash);
+
+ vars.yParityAndS = bytes32((uint256(vars.v - 27) << 255) | uint256(vars.s));
+ vars.signature = abi.encodePacked(vars.r, vars.yParityAndS);
+
+ vars.signerAddr = vm.addr(params.signerPk);
+
+ recovery.queuePayload(params.wallet, vars.signerAddr, params.payload, vars.signature);
+
+ vm.warp(block.timestamp + params.passedTime);
+
+ vars.parts = "";
+ for (uint256 i = 0; i < params.suffixes.length; i++) {
+ vars.parts = string.concat(
+ vars.parts,
+ "signer:",
+ vm.toString(params.suffixes[i].signer),
+ ":",
+ vm.toString(params.suffixes[i].requiredDeltaTime),
+ ":",
+ vm.toString(params.suffixes[i].minTimestamp),
+ " "
+ );
+ }
+
+ vars.parts = string.concat(
+ vars.parts,
+ "signer:",
+ vm.toString(vars.signerAddr),
+ ":",
+ vm.toString(params.requiredDeltaTime),
+ ":",
+ vm.toString(params.minTimestamp)
+ );
+
+ for (uint256 i = 0; i < params.prefixes.length; i++) {
+ vars.parts = string.concat(
+ vars.parts,
+ " signer:",
+ vm.toString(params.prefixes[i].signer),
+ ":",
+ vm.toString(params.prefixes[i].requiredDeltaTime),
+ ":",
+ vm.toString(params.prefixes[i].minTimestamp)
+ );
+ }
+
+ vars.rpcRoot = PrimitivesRPC.recoveryHashFromLeaves(vm, vars.parts);
+
+ vars.encoded = PrimitivesRPC.recoveryTrim(vm, vars.parts, vars.signerAddr);
+ vm.prank(params.wallet);
+ vars.recoveredRoot = recovery.recoverSapientSignatureCompact(vars.payloadHash, vars.encoded);
+ assertEq(vars.recoveredRoot, vars.rpcRoot);
+ }
+
+ function test_recover_sapient_signature_compact_fail_minTimestamp(
+ test_recover_sapient_signature_compact_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+ params.startTime = uint64(bound(params.startTime, 1, type(uint64).max - 1000));
+ params.minTimestamp = uint64(bound(params.minTimestamp, params.startTime + 1, type(uint64).max));
+ params.requiredDeltaTime = uint24(bound(params.requiredDeltaTime, 0, type(uint24).max));
+ params.passedTime = uint64(bound(params.passedTime, 0, type(uint64).max - params.startTime));
+
+ vm.warp(params.startTime);
+
+ params.signerPk = boundPk(params.signerPk);
+
+ test_recover_sapient_signature_compact_vars memory vars;
+ vars.recoveryPayloadHash = recovery.recoveryPayloadHash(params.wallet, params.payload);
+ vars.payloadHash = Payload.hashFor(params.payload, params.wallet);
+ (vars.v, vars.r, vars.s) = vm.sign(params.signerPk, vars.recoveryPayloadHash);
+
+ vars.yParityAndS = bytes32((uint256(vars.v - 27) << 255) | uint256(vars.s));
+ vars.signature = abi.encodePacked(vars.r, vars.yParityAndS);
+
+ vars.signerAddr = vm.addr(params.signerPk);
+
+ recovery.queuePayload(params.wallet, vars.signerAddr, params.payload, vars.signature);
+ assertEq(recovery.timestampForQueuedPayload(params.wallet, vars.signerAddr, vars.payloadHash), params.startTime);
+
+ vm.warp(params.startTime + params.passedTime);
+
+ vars.parts = "";
+ for (uint256 i = 0; i < params.suffixes.length; i++) {
+ vars.parts = string.concat(
+ vars.parts,
+ "signer:",
+ vm.toString(params.suffixes[i].signer),
+ ":",
+ vm.toString(params.suffixes[i].requiredDeltaTime),
+ ":",
+ vm.toString(params.suffixes[i].minTimestamp),
+ " "
+ );
+ }
+ vars.parts = string.concat(
+ vars.parts,
+ "signer:",
+ vm.toString(vars.signerAddr),
+ ":",
+ vm.toString(params.requiredDeltaTime),
+ ":",
+ vm.toString(params.minTimestamp)
+ );
+ for (uint256 i = 0; i < params.prefixes.length; i++) {
+ vars.parts = string.concat(
+ vars.parts,
+ " signer:",
+ vm.toString(params.prefixes[i].signer),
+ ":",
+ vm.toString(params.prefixes[i].requiredDeltaTime),
+ ":",
+ vm.toString(params.prefixes[i].minTimestamp)
+ );
+ }
+ vars.encoded = PrimitivesRPC.recoveryTrim(vm, vars.parts, vars.signerAddr);
+
+ vm.prank(params.wallet);
+ vm.expectRevert(abi.encodeWithSelector(Recovery.QueueNotReady.selector, params.wallet, vars.payloadHash));
+ recovery.recoverSapientSignatureCompact(vars.payloadHash, vars.encoded);
+ }
+
+ function test_recover_sapient_signature_compact_fail_deltaTime(
+ test_recover_sapient_signature_compact_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+ params.startTime = uint64(bound(params.startTime, 1, type(uint64).max - type(uint24).max - 1));
+ params.minTimestamp = uint64(bound(params.minTimestamp, 0, params.startTime));
+ params.requiredDeltaTime = uint24(bound(params.requiredDeltaTime, 1, type(uint24).max));
+ params.passedTime = uint64(bound(params.passedTime, 0, params.requiredDeltaTime - 1));
+
+ vm.warp(params.startTime);
+
+ params.signerPk = boundPk(params.signerPk);
+
+ test_recover_sapient_signature_compact_vars memory vars;
+ vars.recoveryPayloadHash = recovery.recoveryPayloadHash(params.wallet, params.payload);
+ vars.payloadHash = Payload.hashFor(params.payload, params.wallet);
+ (vars.v, vars.r, vars.s) = vm.sign(params.signerPk, vars.recoveryPayloadHash);
+
+ vars.yParityAndS = bytes32((uint256(vars.v - 27) << 255) | uint256(vars.s));
+ vars.signature = abi.encodePacked(vars.r, vars.yParityAndS);
+
+ vars.signerAddr = vm.addr(params.signerPk);
+
+ recovery.queuePayload(params.wallet, vars.signerAddr, params.payload, vars.signature);
+ assertEq(recovery.timestampForQueuedPayload(params.wallet, vars.signerAddr, vars.payloadHash), params.startTime);
+
+ vm.warp(params.startTime + params.passedTime);
+
+ vars.parts = "";
+ for (uint256 i = 0; i < params.suffixes.length; i++) {
+ vars.parts = string.concat(
+ vars.parts,
+ "signer:",
+ vm.toString(params.suffixes[i].signer),
+ ":",
+ vm.toString(params.suffixes[i].requiredDeltaTime),
+ ":",
+ vm.toString(params.suffixes[i].minTimestamp),
+ " "
+ );
+ }
+ vars.parts = string.concat(
+ vars.parts,
+ "signer:",
+ vm.toString(vars.signerAddr),
+ ":",
+ vm.toString(params.requiredDeltaTime),
+ ":",
+ vm.toString(params.minTimestamp)
+ );
+ for (uint256 i = 0; i < params.prefixes.length; i++) {
+ vars.parts = string.concat(
+ vars.parts,
+ " signer:",
+ vm.toString(params.prefixes[i].signer),
+ ":",
+ vm.toString(params.prefixes[i].requiredDeltaTime),
+ ":",
+ vm.toString(params.prefixes[i].minTimestamp)
+ );
+ }
+ vars.encoded = PrimitivesRPC.recoveryTrim(vm, vars.parts, vars.signerAddr);
+
+ vm.prank(params.wallet);
+ vm.expectRevert(abi.encodeWithSelector(Recovery.QueueNotReady.selector, params.wallet, vars.payloadHash));
+ recovery.recoverSapientSignatureCompact(vars.payloadHash, vars.encoded);
+ }
+
+ function test_recover_fail_invalid_signature_flag(
+ address _wallet,
+ bytes32 _payloadHash,
+ uint8 _invalidSignatureFlag,
+ bytes calldata _suffix
+ ) external {
+ if (
+ _invalidSignatureFlag == 1 // Recovery.FLAG_RECOVERY_LEAF
+ || _invalidSignatureFlag == 3 // Recovery.FLAG_NODE
+ || _invalidSignatureFlag == 4 // Recovery.FLAG_BRANCH
+ ) {
+ _invalidSignatureFlag = uint8(0);
+ }
+
+ vm.prank(_wallet);
+ vm.expectRevert(abi.encodeWithSelector(Recovery.InvalidSignatureFlag.selector, _invalidSignatureFlag));
+ recovery.recoverSapientSignatureCompact(_payloadHash, abi.encodePacked(_invalidSignatureFlag, _suffix));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/Attestation.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/Attestation.t.sol
new file mode 100644
index 000000000..1ff90a83c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/Attestation.t.sol
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Attestation, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+
+import { AdvTest } from "../../utils/TestUtils.sol";
+import { Vm } from "forge-std/Test.sol";
+
+contract AttestationImp {
+
+ function toPacked(
+ Attestation memory attestation
+ ) external pure returns (bytes memory encoded) {
+ return LibAttestation.toPacked(attestation);
+ }
+
+ function fromPacked(
+ bytes calldata encoded,
+ uint256 pointer
+ ) external pure returns (Attestation memory attestation, uint256 newPointer) {
+ return LibAttestation.fromPacked(encoded, pointer);
+ }
+
+}
+
+contract AttestationTest is AdvTest {
+
+ AttestationImp public attestationImp;
+
+ function setUp() public {
+ attestationImp = new AttestationImp();
+ }
+
+ function test_packAndUnpackAttestation(
+ Attestation memory attestation
+ ) external view {
+ bytes memory packed = attestationImp.toPacked(attestation);
+ (Attestation memory unpacked, uint256 pointer) = attestationImp.fromPacked(packed, 0);
+
+ assertEq(pointer, packed.length, "pointer");
+
+ assertEq(attestation.approvedSigner, unpacked.approvedSigner, "approvedSigner");
+ assertEq(attestation.identityType, unpacked.identityType, "identityType");
+ assertEq(attestation.issuerHash, unpacked.issuerHash, "issuerHash");
+ assertEq(attestation.audienceHash, unpacked.audienceHash, "audienceHash");
+ assertEq(attestation.applicationData, unpacked.applicationData, "applicationData");
+ assertEq(attestation.authData.redirectUrl, unpacked.authData.redirectUrl, "authData.redirectUrl");
+ assertEq(attestation.authData.issuedAt, unpacked.authData.issuedAt, "authData.issuedAt");
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/Permission.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/Permission.t.sol
new file mode 100644
index 000000000..6dd40dc71
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/Permission.t.sol
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Test } from "forge-std/Test.sol";
+
+import {
+ LibPermission, ParameterOperation, ParameterRule, Permission
+} from "src/extensions/sessions/explicit/Permission.sol";
+
+contract LibPermissionHarness {
+
+ function readPermission(bytes calldata encoded, uint256 pointer) public pure returns (Permission memory, uint256) {
+ return LibPermission.readPermission(encoded, pointer);
+ }
+
+ function toPacked(
+ Permission calldata permission
+ ) public pure returns (bytes memory) {
+ return LibPermission.toPacked(permission);
+ }
+
+}
+
+contract PermissionTest is Test {
+
+ LibPermissionHarness harness;
+
+ function setUp() public {
+ harness = new LibPermissionHarness();
+ }
+
+ // Forge can't handle inputting enums so we declare the structs here
+ struct PermissionTestInput {
+ address target;
+ ParameterRuleTestInput[] rules;
+ }
+
+ struct ParameterRuleTestInput {
+ bool cumulative;
+ uint8 operation;
+ bytes32 value;
+ uint256 offset;
+ bytes32 mask;
+ }
+
+ function test_fail_packRulesLengthExceedsMax(
+ PermissionTestInput memory input
+ ) public {
+ vm.assume(input.rules.length > 0);
+ Permission memory permission = _toPermission(input);
+ uint256 maxRulesLength = type(uint8).max;
+ if (permission.rules.length <= maxRulesLength) {
+ ParameterRule[] memory rules = new ParameterRule[](maxRulesLength + 1);
+ for (uint256 i = 0; i < permission.rules.length; i++) {
+ rules[i] = permission.rules[i];
+ }
+ // Add more rules
+ for (uint256 i = permission.rules.length; i < maxRulesLength + 1; i++) {
+ rules[i] = permission.rules[i % permission.rules.length];
+ }
+ permission.rules = rules;
+ }
+ vm.expectRevert(LibPermission.RulesLengthExceedsMax.selector);
+ harness.toPacked(permission);
+ }
+
+ function test_packAndRead(
+ PermissionTestInput memory input
+ ) public view {
+ Permission memory permission = _toPermission(input);
+ uint256 maxRulesLength = type(uint8).max;
+ if (permission.rules.length > maxRulesLength) {
+ ParameterRule[] memory rules = permission.rules;
+ uint256 rulesLength = bound(rules.length, 0, maxRulesLength); // Re randomize length
+ assembly {
+ mstore(rules, rulesLength)
+ }
+ permission.rules = rules;
+ }
+
+ bytes memory encoded = harness.toPacked(permission);
+ Permission memory decoded;
+ uint256 pointer;
+ (decoded, pointer) = harness.readPermission(encoded, pointer);
+ assertEq(pointer, encoded.length);
+ assertEq(decoded.target, permission.target);
+ assertEq(decoded.rules.length, permission.rules.length);
+ for (uint256 i = 0; i < permission.rules.length; i++) {
+ assertEq(decoded.rules[i].cumulative, permission.rules[i].cumulative);
+ assertEq(uint8(decoded.rules[i].operation), uint8(permission.rules[i].operation));
+ assertEq(decoded.rules[i].value, permission.rules[i].value);
+ assertEq(decoded.rules[i].offset, permission.rules[i].offset);
+ assertEq(decoded.rules[i].mask, permission.rules[i].mask);
+ }
+ }
+
+ function test_packAndReadAtPointer(
+ PermissionTestInput memory input,
+ bytes memory prepend,
+ bytes memory append
+ ) public view {
+ Permission memory permission = _toPermission(input);
+ uint256 maxRulesLength = type(uint8).max;
+ if (permission.rules.length > maxRulesLength) {
+ ParameterRule[] memory rules = permission.rules;
+ uint256 rulesLength = bound(rules.length, 0, maxRulesLength); // Re randomize length
+ assembly {
+ mstore(rules, rulesLength)
+ }
+ permission.rules = rules;
+ }
+
+ bytes memory encoded = harness.toPacked(permission);
+ bytes memory encodedSurrounded = abi.encodePacked(prepend, encoded, append);
+ Permission memory decoded;
+ uint256 pointer = prepend.length;
+ (decoded, pointer) = harness.readPermission(encodedSurrounded, pointer);
+ assertEq(pointer, prepend.length + encoded.length);
+ assertEq(decoded.target, permission.target);
+ assertEq(decoded.rules.length, permission.rules.length);
+ for (uint256 i = 0; i < permission.rules.length; i++) {
+ assertEq(decoded.rules[i].cumulative, permission.rules[i].cumulative);
+ assertEq(uint8(decoded.rules[i].operation), uint8(permission.rules[i].operation));
+ assertEq(decoded.rules[i].value, permission.rules[i].value);
+ assertEq(decoded.rules[i].offset, permission.rules[i].offset);
+ assertEq(decoded.rules[i].mask, permission.rules[i].mask);
+ }
+ }
+
+ function _toPermission(
+ PermissionTestInput memory input
+ ) internal pure returns (Permission memory) {
+ ParameterRule[] memory rules = new ParameterRule[](input.rules.length);
+ for (uint256 i = 0; i < input.rules.length; i++) {
+ uint256 operation = bound(input.rules[i].operation, 0, 3);
+ ParameterOperation parameterOperation;
+ if (operation == 0) {
+ parameterOperation = ParameterOperation.EQUAL;
+ } else if (operation == 1) {
+ parameterOperation = ParameterOperation.NOT_EQUAL;
+ } else if (operation == 2) {
+ parameterOperation = ParameterOperation.GREATER_THAN_OR_EQUAL;
+ } else if (operation == 3) {
+ parameterOperation = ParameterOperation.LESS_THAN_OR_EQUAL;
+ }
+ rules[i] = ParameterRule({
+ cumulative: input.rules[i].cumulative,
+ operation: parameterOperation,
+ value: input.rules[i].value,
+ offset: input.rules[i].offset,
+ mask: input.rules[i].mask
+ });
+ }
+ return Permission({ target: input.target, rules: rules });
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionCalls.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionCalls.t.sol
new file mode 100644
index 000000000..2162b7157
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionCalls.t.sol
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Vm, console } from "forge-std/Test.sol";
+import { SessionTestBase } from "test/extensions/sessions/SessionTestBase.sol";
+
+import { Emitter } from "test/mocks/Emitter.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { SessionErrors } from "src/extensions/sessions/SessionErrors.sol";
+import { SessionManager } from "src/extensions/sessions/SessionManager.sol";
+import { SessionSig } from "src/extensions/sessions/SessionSig.sol";
+import { SessionPermissions } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Calls } from "src/modules/Calls.sol";
+import { ERC4337v07 } from "src/modules/ERC4337v07.sol";
+import { Payload } from "src/modules/Payload.sol";
+import { ISapient } from "src/modules/interfaces/ISapient.sol";
+
+/// @notice Explicit session integration tests.
+contract SessionCallsTest is SessionTestBase {
+
+ Factory public factory;
+ Stage1Module public module;
+ SessionManager public sessionManager;
+ Vm.Wallet public sessionWallet;
+ Vm.Wallet public identityWallet;
+ MockContract public target;
+
+ function setUp() public {
+ sessionWallet = vm.createWallet("session");
+ identityWallet = vm.createWallet("identity");
+ sessionManager = new SessionManager();
+ factory = new Factory();
+ module = new Stage1Module(address(factory), address(0));
+ target = new MockContract();
+ }
+
+ function _validCall(Payload.Call memory call, bool callRevert) internal view returns (Payload.Call memory) {
+ call.to = address(target);
+ call.behaviorOnError = bound(call.behaviorOnError, 0, 2);
+ call.value = bound(call.value, 0, 1 ether);
+ call.data = abi.encodeWithSelector(MockContract.willRevert.selector, callRevert);
+ call.gasLimit = bound(call.gasLimit, 0, 1); // Pass or fail due to gas limit
+
+ // FIXME Remove. This is here to make it pass
+ // call.behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ // call.onlyFallback = false;
+ // call.data = abi.encodeWithSelector(MockContract.willRevert.selector, false);
+
+ return call;
+ }
+
+ function test_fuzzForSkippingIncrementCall(
+ Payload.Call memory call1,
+ Payload.Call memory call2,
+ bool call1Revert,
+ bool call2Revert
+ ) public {
+ Payload.Decoded memory payload = _buildPayload(3);
+ // Fuzzes: Behavior, value, onlyFallback, gasLimit, contract call reverts
+ payload.calls[1] = _validCall(call1, call1Revert);
+ payload.calls[2] = _validCall(call2, call2Revert);
+
+ // totalValue is calculated from calls[1] and calls[2]
+ uint256 totalValue = payload.calls[1].value + payload.calls[2].value;
+ vm.assume(totalValue > 0); // Required to use an increment permission
+
+ // Create the increment call and place it at index 0
+ UsageLimit[] memory usageLimits = new UsageLimit[](1);
+ usageLimits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, sessionManager.VALUE_TRACKING_ADDRESS())),
+ usageAmount: totalValue
+ });
+
+ // Manually construct the increment call to ensure it's valid, not fuzzed.
+ // The original test fuzzed this call, but now it must be valid for the test setup.
+ payload.calls[0] = Payload.Call({
+ to: address(sessionManager),
+ data: abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, usageLimits),
+ value: 0, // Increment calls should not have value
+ gasLimit: 0, // No gas limit
+ delegateCall: false,
+ onlyFallback: false, // Must not be a fallback
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR // Must revert on error
+ });
+
+ // Create the valid explicit session
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: totalValue,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(target), rules: new ParameterRule[](0) });
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ bytes32 sessionImageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+
+ // Create the wallet config
+ string memory config;
+ {
+ string memory ce = string(
+ abi.encodePacked("sapient:", vm.toString(sessionImageHash), ":", vm.toString(address(sessionManager)), ":1")
+ );
+ config = PrimitivesRPC.newConfig(vm, 1, 0, ce);
+ }
+ bytes32 imageHash = PrimitivesRPC.getImageHash(vm, config);
+ Stage1Module wallet = Stage1Module(payable(factory.deploy(address(module), imageHash)));
+
+ // Fund the wallet
+ vm.deal(address(wallet), totalValue + 1);
+
+ // Sign the payload
+ string[] memory callSignatures = new string[](3);
+ for (uint256 i = 0; i < 3; i++) {
+ string memory sessionSignature =
+ _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(payload, i), sessionWallet);
+ callSignatures[i] = _explicitCallSignatureToJSON(0, sessionSignature);
+ }
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ bytes memory encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, false);
+
+ // Execute the payload
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, payload);
+ try wallet.execute(packedPayload, encodedSignature) {
+ // If execution succeeds, check the increment is updated
+ uint256 usageAmount = sessionManager.getLimitUsage(address(wallet), usageLimits[0].usageHash);
+ assertEq(usageAmount, totalValue, "Usage should increment on successful execution");
+ // It doesn't matter if the wallet spends funds or not
+ // (error and IGNORE, error and IGNORE, increment) is ok
+ } catch (bytes memory reason) {
+ // If the execution reverts, check the wallet balance is unaffected
+ bytes4 errorSelector = bytes4(reason);
+ if (
+ errorSelector == SessionErrors.InvalidBehavior.selector
+ || errorSelector == SessionErrors.InvalidDelegateCall.selector
+ || errorSelector == SessionErrors.InvalidValue.selector || errorSelector == Calls.NotEnoughGas.selector
+ || errorSelector == Calls.Reverted.selector || errorSelector == MockContract.MockError.selector
+ ) {
+ // Should not spend funds or update usage limits
+ assertEq(address(wallet).balance, totalValue + 1, "Wallet balance should not change");
+ uint256 usageAmount = sessionManager.getLimitUsage(address(wallet), usageLimits[0].usageHash);
+ assertEq(usageAmount, 0, "Usage should not increment");
+ } else if (errorSelector == SessionErrors.InvalidLimitUsageIncrement.selector) {
+ // This case is now more complex. A failure here could be because the fuzzer made call1 or call2
+ // have an invalid behavior that would cause the increment to be skipped.
+ // The simplest way to handle this is to accept that an InvalidLimitUsageIncrement revert
+ // means the wallet balance and usage should not change.
+ assertEq(
+ address(wallet).balance, totalValue + 1, "Wallet balance should not change on InvalidLimitUsageIncrement"
+ );
+ uint256 usageAmount = sessionManager.getLimitUsage(address(wallet), usageLimits[0].usageHash);
+ assertEq(usageAmount, 0, "Usage should not increment on InvalidLimitUsageIncrement");
+ } else {
+ revert("Got an unexpected error. Update tests to handle this error.");
+ }
+ }
+ }
+
+ function test_fuzzForSkippingIncrementCall2(
+ Payload.Call memory callIncrement,
+ Payload.Call memory call1,
+ Payload.Call memory call2,
+ Payload.Call memory call3,
+ bool call1Revert,
+ bool call2Revert,
+ bool call3Revert
+ ) public {
+ Payload.Decoded memory payload = _buildPayload(4);
+ // Fuzzes: Behavior, value, onlyFallback, gasLimit, contract call reverts
+ payload.calls[1] = _validCall(call1, call1Revert);
+ payload.calls[2] = _validCall(call2, call2Revert);
+ payload.calls[3] = _validCall(call3, call3Revert);
+
+ // totalValue is calculated from calls[1] through calls[3]
+ uint256 totalValue = payload.calls[1].value + payload.calls[2].value + payload.calls[3].value;
+ vm.assume(totalValue > 0); // Required to use an increment permission
+
+ // Create the increment call and place it at index 0
+ UsageLimit[] memory usageLimits = new UsageLimit[](1);
+ usageLimits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, sessionManager.VALUE_TRACKING_ADDRESS())),
+ usageAmount: totalValue
+ });
+
+ callIncrement = _validCall(callIncrement, false);
+ callIncrement.to = address(sessionManager);
+ callIncrement.data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, usageLimits);
+ payload.calls[0] = callIncrement;
+
+ // Create the valid explicit session
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: totalValue,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(target), rules: new ParameterRule[](0) });
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ bytes32 sessionImageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+
+ // Create the wallet config
+ string memory config;
+ {
+ string memory ce = string(
+ abi.encodePacked("sapient:", vm.toString(sessionImageHash), ":", vm.toString(address(sessionManager)), ":1")
+ );
+ config = PrimitivesRPC.newConfig(vm, 1, 0, ce);
+ }
+ bytes32 imageHash = PrimitivesRPC.getImageHash(vm, config);
+ Stage1Module wallet = Stage1Module(payable(factory.deploy(address(module), imageHash)));
+
+ // Fund the wallet
+ vm.deal(address(wallet), totalValue + 1);
+
+ // Sign the payload
+ string[] memory callSignatures = new string[](4);
+ for (uint256 i; i < 4; i++) {
+ string memory sessionSignature =
+ _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(payload, i), sessionWallet);
+ callSignatures[i] = _explicitCallSignatureToJSON(0, sessionSignature);
+ }
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ bytes memory encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, false);
+
+ // Execute the payload
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, payload);
+ try wallet.execute(packedPayload, encodedSignature) {
+ // If execution succeeds, check the increment is updated
+ uint256 usageAmount = sessionManager.getLimitUsage(address(wallet), usageLimits[0].usageHash);
+ assertEq(usageAmount, totalValue, "Usage should increment on successful execution");
+ // It doesn't matter if the wallet spends funds or not
+ // (error and IGNORE, error and IGNORE, increment) is ok
+ } catch (bytes memory reason) {
+ // If the execution reverts, check the wallet balance is unaffected
+ bytes4 errorSelector = bytes4(reason);
+ if (
+ errorSelector == SessionErrors.InvalidBehavior.selector
+ || errorSelector == SessionErrors.InvalidDelegateCall.selector
+ || errorSelector == SessionErrors.InvalidValue.selector || errorSelector == Calls.NotEnoughGas.selector
+ || errorSelector == Calls.Reverted.selector || errorSelector == MockContract.MockError.selector
+ ) {
+ // Should not spend funds or update usage limits
+ assertEq(address(wallet).balance, totalValue + 1, "Wallet balance should not change");
+ uint256 usageAmount = sessionManager.getLimitUsage(address(wallet), usageLimits[0].usageHash);
+ assertEq(usageAmount, 0, "Usage should not increment");
+ } else if (errorSelector == SessionErrors.InvalidLimitUsageIncrement.selector) {
+ if (callIncrement.behaviorOnError != Payload.BEHAVIOR_REVERT_ON_ERROR || callIncrement.onlyFallback) {
+ // Expected. Should not spend funds or update usage limits
+ assertEq(address(wallet).balance, totalValue + 1, "Wallet balance should not change");
+ uint256 usageAmount = sessionManager.getLimitUsage(address(wallet), usageLimits[0].usageHash);
+ assertEq(usageAmount, 0, "Usage should not increment");
+ } else {
+ revert("Test not correctly fuzzed. This should always pass.");
+ }
+ } else {
+ revert("Got an unexpected error. Update tests to handle this error.");
+ }
+ }
+ }
+
+}
+
+contract MockContract {
+
+ error MockError();
+
+ function willRevert(
+ bool doRevert
+ ) public payable {
+ if (doRevert) {
+ revert MockError();
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionManager.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionManager.t.sol
new file mode 100644
index 000000000..812eb6381
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionManager.t.sol
@@ -0,0 +1,855 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Vm } from "forge-std/Vm.sol";
+import { SessionTestBase } from "test/extensions/sessions/SessionTestBase.sol";
+
+import { Emitter } from "test/mocks/Emitter.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { SessionErrors } from "src/extensions/sessions/SessionErrors.sol";
+import { SessionManager } from "src/extensions/sessions/SessionManager.sol";
+import { SessionSig } from "src/extensions/sessions/SessionSig.sol";
+import { SessionPermissions } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Payload } from "src/modules/Payload.sol";
+import { ISapient } from "src/modules/interfaces/ISapient.sol";
+
+import { CanReenter } from "test/mocks/CanReenter.sol";
+import { MockERC20 } from "test/mocks/MockERC20.sol";
+
+contract SessionManagerTest is SessionTestBase {
+
+ SessionManager public sessionManager;
+ Vm.Wallet public sessionWallet;
+ Vm.Wallet public identityWallet;
+ Emitter public emitter;
+
+ function setUp() public {
+ sessionManager = new SessionManager();
+ sessionWallet = vm.createWallet("session");
+ identityWallet = vm.createWallet("identity");
+ emitter = new Emitter();
+ }
+
+ /// @notice Valid explicit session test.
+ function testValidExplicitSessionSignature(
+ bytes4 selector,
+ uint256 param,
+ uint256 value,
+ address explicitTarget,
+ address explicitTarget2,
+ bool useChainId
+ ) public {
+ vm.assume(explicitTarget != explicitTarget2);
+ vm.assume(value > 0);
+ vm.assume(param > 0);
+ vm.assume(explicitTarget != address(sessionManager));
+ vm.assume(explicitTarget2 != address(sessionManager));
+ bytes memory callData = abi.encodeWithSelector(selector, param);
+
+ // --- Session Permissions ---
+ // Create a SessionPermissions struct granting permission for calls to explicitTarget.
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: useChainId ? block.chainid : 0,
+ valueLimit: value,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](2)
+ });
+ // Permission with an empty rules set allows all calls to the target.
+ ParameterRule[] memory rules = new ParameterRule[](2);
+ // Rules for explicitTarget in call 0.
+ rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(uint256(uint32(selector)) << 224),
+ offset: 0,
+ mask: bytes32(uint256(uint32(0xffffffff)) << 224)
+ });
+ rules[1] = ParameterRule({
+ cumulative: true,
+ operation: ParameterOperation.LESS_THAN_OR_EQUAL,
+ value: bytes32(param),
+ offset: 4, // offset the param (selector is 4 bytes)
+ mask: bytes32(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
+ });
+ sessionPerms.permissions[0] = Permission({ target: explicitTarget, rules: rules });
+ sessionPerms.permissions[1] = Permission({ target: explicitTarget2, rules: new ParameterRule[](0) }); // Unlimited access
+
+ // Build a payload with two calls:
+ // Call 0: call not requiring incrementUsageLimit
+ // Call 1: call requiring incrementUsageLimit
+ // Call 2: the required incrementUsageLimit call (self–call)
+ Payload.Decoded memory payload = _buildPayload(3);
+
+ // --- Explicit Call 1 ---
+ payload.calls[1] = Payload.Call({
+ to: explicitTarget,
+ value: value,
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // --- Explicit Call 2 ---
+ payload.calls[2] = Payload.Call({
+ to: explicitTarget2,
+ value: 0,
+ data: callData, // Reuse this because permission for this target is open
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // --- Increment Usage Limit ---
+ {
+ UsageLimit[] memory limits = new UsageLimit[](2);
+ limits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, sessionPerms.permissions[0], uint256(1))),
+ usageAmount: param
+ });
+ limits[1] =
+ UsageLimit({ usageHash: keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS)), usageAmount: value });
+ payload.calls[0] = Payload.Call({
+ to: address(sessionManager),
+ value: 0,
+ data: abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+
+ uint8[] memory permissionIdxs = new uint8[](3);
+ permissionIdxs[0] = 0; // Call 0
+ permissionIdxs[1] = 0; // Call 1
+ permissionIdxs[2] = 1; // Call 2
+
+ (bytes32 imageHash, bytes memory encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, permissionIdxs);
+
+ vm.prank(sessionWallet.addr);
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ function testIncrementReentrancy() external {
+ MockERC20 token = new MockERC20();
+ CanReenter canReenter = new CanReenter();
+ Factory factory = new Factory();
+ Stage1Module stage1Module = new Stage1Module(address(factory), address(0));
+ Vm.Wallet memory badGuy = vm.createWallet("badGuy");
+
+ // --- Session Permissions ---
+ // Create a SessionPermissions struct granting permission for calls to explicitTarget.
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](2)
+ });
+ // Permission with an empty rules set allows all calls to the target.
+ ParameterRule[] memory rules = new ParameterRule[](2);
+ rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(uint256(uint32(MockERC20.transfer.selector)) << 224),
+ offset: 0,
+ mask: bytes32(uint256(uint32(0xffffffff)) << 224)
+ });
+ rules[1] = ParameterRule({
+ cumulative: true,
+ operation: ParameterOperation.LESS_THAN_OR_EQUAL,
+ value: bytes32(uint256(1 ether)),
+ offset: 4 + 32, // offset the param (selector is 4 bytes)
+ mask: bytes32(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(token), rules: rules });
+ sessionPerms.permissions[1] = Permission({ target: address(canReenter), rules: new ParameterRule[](0) }); // Unlimited access
+
+ // Build the session topology using PrimitiveRPC.
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+
+ // Topology hash
+ bytes32 topologyHash = PrimitivesRPC.sessionImageHash(vm, topology);
+
+ // Create wallet for this topology
+ string memory config = PrimitivesRPC.newConfig(
+ vm,
+ 1,
+ 0,
+ string(
+ abi.encodePacked(
+ "sapient:", vm.toString(topologyHash), ":", vm.toString(address(sessionManager)), ":", vm.toString(uint256(1))
+ )
+ )
+ );
+ bytes32 configHash = PrimitivesRPC.getImageHash(vm, config);
+ address payable wallet = payable(factory.deploy(address(stage1Module), configHash));
+
+ // Transfer tokens to the wallet (2 ether)
+ token.transfer(wallet, 2 ether);
+
+ // Build the reentrant payload
+ // Call 0: update the usage limit
+ // Call 1: transfer 0.5 ether to the bad guy
+ Payload.Decoded memory reentrantPayload = _buildPayload(2);
+ reentrantPayload.nonce = 1;
+
+ UsageLimit[] memory reentrantLimits = new UsageLimit[](1);
+ reentrantLimits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, sessionPerms.permissions[0], uint256(1))),
+ usageAmount: 1 ether
+ });
+
+ // Call 0: update the usage limit
+ reentrantPayload.calls[0] = Payload.Call({
+ to: address(sessionManager),
+ value: 0,
+ data: abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, reentrantLimits),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ reentrantPayload.calls[1] = Payload.Call({
+ to: address(token),
+ value: 0,
+ data: abi.encodeWithSelector(token.transfer.selector, badGuy.addr, 1 ether),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Encode the call signatures for the reentrant payload
+ string[] memory reentrantCallSignatures = new string[](2);
+ string memory sessionSignature =
+ _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(reentrantPayload, 0), sessionWallet);
+ reentrantCallSignatures[0] = _explicitCallSignatureToJSON(0, sessionSignature);
+ sessionSignature = _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(reentrantPayload, 1), sessionWallet);
+ reentrantCallSignatures[1] = _explicitCallSignatureToJSON(0, sessionSignature);
+ address[] memory reentrantExplicitSigners = new address[](1);
+ reentrantExplicitSigners[0] = sessionWallet.addr;
+ address[] memory reentrantImplicitSigners = new address[](0);
+ bytes memory reentrantEncodedSig = PrimitivesRPC.sessionEncodeCallSignatures(
+ vm, topology, reentrantCallSignatures, reentrantExplicitSigners, reentrantImplicitSigners
+ );
+
+ // Encode the main signature for the reentrant payload
+ bytes memory reentrantMainSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(reentrantEncodedSig))),
+ false
+ );
+
+ // Pack reentrant payload
+ bytes memory reentrantPackedPayload = PrimitivesRPC.toPackedPayload(vm, reentrantPayload);
+
+ // Encode the execute function call
+ bytes memory reentrantExecuteData = abi.encodeWithSelector(
+ canReenter.doAnotherCall.selector,
+ address(wallet),
+ abi.encodeWithSelector(Stage1Module(wallet).execute.selector, reentrantPackedPayload, reentrantMainSignature)
+ );
+
+ // Build a payload with two calls:
+ // Call 1: transfer tokens to the bad guy
+ // Call 2: re-enter and transfer more tokens to the bad guy
+ // Call 3: the required incrementUsageLimit call (self–call)
+ Payload.Decoded memory payload = _buildPayload(3);
+
+ // --- Explicit Call 0 ---
+ UsageLimit[] memory limits = new UsageLimit[](1);
+ limits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, sessionPerms.permissions[0], uint256(0.5 ether))),
+ usageAmount: 0.5 ether
+ });
+
+ payload.calls[0] = Payload.Call({
+ to: address(sessionManager),
+ value: 0,
+ data: abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // --- Explicit Call 1 ---
+ payload.calls[1] = Payload.Call({
+ to: address(token),
+ value: 0,
+ data: abi.encodeWithSelector(token.transfer.selector, badGuy.addr, 1 ether),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // --- Explicit Call 2 ---
+ payload.calls[2] = Payload.Call({
+ to: address(canReenter),
+ value: 0,
+ data: reentrantExecuteData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // --- Call Signatures ---
+ string[] memory callSignatures = new string[](3);
+ {
+ // Sign the explicit call (call 0) using the session key.
+ sessionSignature = _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(payload, 0), sessionWallet);
+ callSignatures[0] = _explicitCallSignatureToJSON(0, sessionSignature);
+ // Sign the explicit call (call 1) using the session key.
+ sessionSignature = _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(payload, 1), sessionWallet);
+ callSignatures[1] = _explicitCallSignatureToJSON(0, sessionSignature);
+ // Sign the self call (call 2) using the session key.
+ sessionSignature = _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(payload, 2), sessionWallet);
+ callSignatures[2] = _explicitCallSignatureToJSON(1, sessionSignature);
+ }
+
+ // Encode the full signature.
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ bytes memory encodedSig =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+
+ // Encode the main signature
+ bytes memory mainSignature = PrimitivesRPC.toEncodedSignature(
+ vm,
+ config,
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(encodedSig))),
+ false
+ );
+
+ // Execute the payload
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, payload);
+ vm.expectRevert();
+ Stage1Module(wallet).execute(packedPayload, mainSignature);
+
+ // Bad guy should have 0 funds
+ assertEq(token.balanceOf(badGuy.addr), 0);
+ }
+
+ function _prepareIncrementOverMultipleCalls(
+ address wallet,
+ address target,
+ uint256 startIncrement,
+ uint256 value1,
+ uint256 value2,
+ uint256 ruleValue
+ ) internal returns (Payload.Decoded memory payload, bytes32 imageHash, bytes memory encodedSig) {
+ vm.assume(target.code.length == 0);
+
+ // Session permissions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](1) });
+ sessionPerms.permissions[0].rules[0] = ParameterRule({
+ cumulative: true,
+ operation: ParameterOperation.LESS_THAN_OR_EQUAL,
+ value: bytes32(uint256(ruleValue)),
+ offset: 0,
+ mask: bytes32(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
+ });
+
+ // Set the initial limit usage
+ UsageLimit[] memory limits = new UsageLimit[](1);
+ limits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, sessionPerms.permissions[0], uint256(0))),
+ usageAmount: startIncrement
+ });
+ vm.prank(wallet);
+ sessionManager.incrementUsageLimit(limits);
+ assertEq(sessionManager.getLimitUsage(wallet, limits[0].usageHash), startIncrement);
+
+ // Call 0: increment the usage limit
+ payload = _buildPayload(3);
+ limits[0].usageAmount = startIncrement + value1 + value2;
+ payload.calls[0] = Payload.Call({
+ to: address(sessionManager),
+ value: 0,
+ data: abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Use limit
+ payload.calls[1] = Payload.Call({
+ to: target,
+ value: 0,
+ data: abi.encodePacked(uint256(value1)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ payload.calls[2] = Payload.Call({
+ to: target,
+ value: 0,
+ data: abi.encodePacked(uint256(value2)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ uint8[] memory permissionIdxs = new uint8[](3);
+
+ (imageHash, encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, permissionIdxs);
+
+ return (payload, imageHash, encodedSig);
+ }
+
+ function testIncrementOverMultipleCalls_Invalid(
+ address wallet,
+ address target,
+ uint256 startIncrement,
+ uint256 value1,
+ uint256 value2,
+ uint256 ruleValue
+ ) public {
+ startIncrement = bound(startIncrement, 0, 1 ether);
+ value1 = bound(value1, 1, 1 ether);
+ value2 = bound(value2, 1, 1 ether);
+
+ ruleValue = bound(ruleValue, 0, startIncrement + value1 + value2 - 1);
+
+ Payload.Decoded memory payload;
+ bytes memory encodedSig;
+ (payload,, encodedSig) =
+ _prepareIncrementOverMultipleCalls(wallet, target, startIncrement, value1, value2, ruleValue);
+
+ vm.prank(wallet);
+ vm.expectRevert(SessionErrors.InvalidPermission.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+ }
+
+ function testIncrementOverMultipleCalls_Valid(
+ address wallet,
+ address target,
+ uint256 startIncrement,
+ uint256 value1,
+ uint256 value2,
+ uint256 ruleValue
+ ) public {
+ vm.assume(target != wallet);
+ startIncrement = bound(startIncrement, 0, 1 ether);
+ value1 = bound(value1, 1, 1 ether);
+ value2 = bound(value2, 1, 1 ether);
+
+ ruleValue = bound(ruleValue, startIncrement + value1 + value2, 100 ether);
+
+ (Payload.Decoded memory payload, bytes32 imageHash, bytes memory encodedSig) =
+ _prepareIncrementOverMultipleCalls(wallet, target, startIncrement, value1, value2, ruleValue);
+
+ vm.prank(wallet);
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ function testInvalidPayloadKindReverts() public {
+ Payload.Decoded memory payload;
+ bytes memory encodedSig;
+
+ payload.kind = Payload.KIND_MESSAGE;
+ vm.expectRevert(SessionErrors.InvalidPayloadKind.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+
+ payload.kind = Payload.KIND_CONFIG_UPDATE;
+ vm.expectRevert(SessionErrors.InvalidPayloadKind.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+
+ payload.kind = Payload.KIND_DIGEST;
+ vm.expectRevert(SessionErrors.InvalidPayloadKind.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+ }
+
+ function testInvalidCallsLengthReverts(
+ bytes memory sig
+ ) public {
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_TRANSACTIONS;
+
+ vm.expectRevert(SessionErrors.InvalidCallsLength.selector);
+ sessionManager.recoverSapientSignature(payload, sig);
+ }
+
+ function testInvalidSpaceReverts(uint160 space, bytes memory sig) public {
+ space = uint160(bound(space, sessionManager.MAX_SPACE() + 1, type(uint160).max));
+
+ Payload.Decoded memory payload;
+
+ vm.expectRevert(SessionErrors.InvalidCallsLength.selector);
+ sessionManager.recoverSapientSignature(payload, sig);
+ }
+
+ /// @notice Test that a call using delegateCall reverts.
+ function testInvalidDelegateCallReverts(Attestation memory attestation, bytes memory data, address target) public {
+ vm.assume(target != address(sessionManager));
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ // Build a payload with one call that erroneously uses delegateCall.
+ uint256 callCount = 1;
+ Payload.Decoded memory payload = _buildPayload(callCount);
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: data,
+ gasLimit: 0,
+ delegateCall: true, // invalid
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ (, bytes memory encodedSig) = _validImplicitSessionSignature(payload);
+
+ vm.expectRevert(SessionErrors.InvalidDelegateCall.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+ }
+
+ /// @notice Valid implicit session test.
+ function testValidImplicitSessionSignature(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ // Build a payload with one call for implicit session.
+ uint256 callCount = 1;
+ Payload.Decoded memory payload = _buildPayload(callCount);
+ payload.calls[0] = Payload.Call({
+ to: address(emitter),
+ value: 0,
+ data: abi.encodeWithSelector(Emitter.implicitEmit.selector),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ (bytes32 imageHash, bytes memory encodedSig) = _validImplicitSessionSignature(payload);
+
+ vm.prank(sessionWallet.addr);
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ /// @notice Test that calls with onlyFallback = true are allowed
+ function testOnlyFallbackCallsAllowed() public {
+ // Build a payload with one call that has onlyFallback = true
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(emitter), // Use emitter instead of explicitTarget for implicit sessions
+ value: 0,
+ data: abi.encodeWithSelector(Emitter.implicitEmit.selector),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: true,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ (bytes32 imageHash, bytes memory encodedSig) = _validImplicitSessionSignature(payload);
+
+ vm.prank(sessionWallet.addr);
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ /// @notice Test that calls with BEHAVIOR_ABORT_ON_ERROR will revert with InvalidBehavior
+ function testBehaviorAbortOnErrorCallsRevert(address target, bytes memory data) public {
+ vm.assume(target != address(sessionManager));
+ // Build a payload with one call that has BEHAVIOR_ABORT_ON_ERROR
+ uint256 callCount = 1;
+ Payload.Decoded memory payload = _buildPayload(callCount);
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: data,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_ABORT_ON_ERROR // This should revert
+ });
+
+ (, bytes memory encodedSig) = _validImplicitSessionSignature(payload);
+
+ vm.expectRevert(SessionErrors.InvalidBehavior.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+ }
+
+ /// @notice Test that calls with onlyFallback = true in explicit sessions are allowed
+ function testExplicitSessionOnlyFallbackAllowed(address target, bytes memory data) public {
+ vm.assume(target != address(sessionManager));
+ // Build a payload with one call: explicit call
+ Payload.Decoded memory payload = _buildPayload(1);
+
+ // First call with onlyFallback = true (should be allowed)
+ // increment call is not allowed since there is no consumption of the usage limit
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: data,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: true,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Session permissions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](0) });
+
+ uint8[] memory permissionIdxs = new uint8[](1);
+ permissionIdxs[0] = 0; // Call 0
+
+ (bytes32 imageHash, bytes memory encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, permissionIdxs);
+
+ vm.prank(sessionWallet.addr);
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ /// @notice Test that the increment call cannot have onlyFallback = true
+ function testIncrementCallOnlyFallbackReverts(address target, bytes memory data) public {
+ vm.assume(target != address(sessionManager));
+ // Build a payload with two calls: explicit call + increment call with onlyFallback
+ uint256 callCount = 2;
+ Payload.Decoded memory payload = _buildPayload(callCount);
+
+ // First call (valid explicit call that will use usage limits)
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 1, // Use some value to trigger usage tracking
+ data: data,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Second call (increment call with onlyFallback = true - should revert)
+ payload.calls[1] = Payload.Call({
+ to: address(sessionManager),
+ value: 0,
+ data: abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, new UsageLimit[](1)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: true, // This should cause the increment call to be skipped
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Session permissions with value limit to trigger usage tracking
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 1, // Set value limit to trigger usage tracking
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](0) });
+
+ uint8[] memory permissionIdxs = new uint8[](2);
+ permissionIdxs[0] = 0; // Call 0
+ permissionIdxs[1] = 0; // Call 1
+
+ (, bytes memory encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, permissionIdxs);
+
+ vm.expectRevert(SessionErrors.InvalidLimitUsageIncrement.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+ }
+
+ /// @notice Test that calls with BEHAVIOR_IGNORE_ERROR in explicit sessions are allowed
+ function testExplicitSessionBehaviorIgnoreErrorAllowed(address target, bytes memory data) public {
+ vm.assume(target != address(sessionManager));
+ Payload.Decoded memory payload = _buildPayload(1);
+
+ // First call with BEHAVIOR_IGNORE_ERROR (should be allowed)
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: data,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_IGNORE_ERROR
+ });
+
+ // Session permissions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](0) });
+
+ (bytes32 imageHash, bytes memory encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, new uint8[](1));
+
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ /// @notice Test that calls with BEHAVIOR_ABORT_ON_ERROR in explicit sessions revert
+ function testExplicitSessionBehaviorAbortOnErrorReverts(address target, bytes memory data) public {
+ vm.assume(target != address(sessionManager));
+ Payload.Decoded memory payload = _buildPayload(1);
+
+ // First call with BEHAVIOR_ABORT_ON_ERROR (should revert)
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: data,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_ABORT_ON_ERROR // This should revert
+ });
+
+ // Session permissions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](0) });
+
+ (, bytes memory encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, new uint8[](1));
+
+ vm.expectRevert(SessionErrors.InvalidBehavior.selector);
+ sessionManager.recoverSapientSignature(payload, encodedSig);
+ }
+
+ /// @notice Test that valid linear execution still works
+ function testValidLinearExecution(address target, bytes memory data) public {
+ vm.assume(target != address(sessionManager));
+ Payload.Decoded memory payload = _buildPayload(1);
+
+ // First call (normal explicit call)
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: data,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR // Valid behavior
+ });
+
+ // Session permissions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](0) });
+
+ (bytes32 imageHash, bytes memory encodedSig) = _validExplicitSessionSignature(payload, sessionPerms, new uint8[](1));
+
+ // This should succeed since all flags are valid for linear execution
+ bytes32 actualImageHash = sessionManager.recoverSapientSignature(payload, encodedSig);
+ assertEq(imageHash, actualImageHash);
+ }
+
+ // ============================================================================
+ // HELPER FUNCTIONS
+ // ============================================================================
+
+ /// @notice Create a valid attestation for testing
+ function _createValidAttestation() internal view returns (Attestation memory) {
+ Attestation memory attestation;
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com";
+ attestation.authData.issuedAt = uint64(block.timestamp);
+ return attestation;
+ }
+
+ function _validImplicitSessionSignature(
+ Payload.Decoded memory payload
+ ) internal returns (bytes32 imageHash, bytes memory encodedSig) {
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ imageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+
+ uint256 callCount = payload.calls.length;
+ string[] memory callSignatures = new string[](callCount);
+ Attestation memory attestation = _createValidAttestation();
+ for (uint256 i; i < callCount; i++) {
+ callSignatures[i] = _createImplicitCallSignature(payload, i, sessionWallet, identityWallet, attestation);
+ }
+
+ address[] memory explicitSigners = new address[](0);
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ encodedSig =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ return (imageHash, encodedSig);
+ }
+
+ function _validExplicitSessionSignature(
+ Payload.Decoded memory payload,
+ SessionPermissions memory sessionPerms,
+ uint8[] memory permissionIdxs
+ ) internal returns (bytes32 imageHash, bytes memory encodedSig) {
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ imageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+
+ uint256 callCount = payload.calls.length;
+ string[] memory callSignatures = new string[](callCount);
+ for (uint256 i; i < callCount; i++) {
+ string memory sessionSignature =
+ _signAndEncodeRSV(SessionSig.hashCallWithReplayProtection(payload, i), sessionWallet);
+ callSignatures[i] = _explicitCallSignatureToJSON(permissionIdxs[i], sessionSignature);
+ }
+
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ encodedSig =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+
+ return (imageHash, encodedSig);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionSig.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionSig.t.sol
new file mode 100644
index 000000000..adf77dc5c
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionSig.t.sol
@@ -0,0 +1,1020 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Vm } from "forge-std/Test.sol";
+import { SessionTestBase } from "test/extensions/sessions/SessionTestBase.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { SessionErrors } from "src/extensions/sessions/SessionErrors.sol";
+import { SessionSig } from "src/extensions/sessions/SessionSig.sol";
+import { SessionPermissions } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import { ParameterOperation, ParameterRule, Permission } from "src/extensions/sessions/explicit/Permission.sol";
+
+import { Attestation, AuthData, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+
+using LibAttestation for Attestation;
+
+contract SessionSigHarness {
+
+ function recover(
+ Payload.Decoded calldata payload,
+ bytes calldata signature
+ ) external view returns (SessionSig.DecodedSignature memory) {
+ return SessionSig.recoverSignature(payload, signature);
+ }
+
+ function recoverConfiguration(
+ bytes calldata encoded
+ ) external pure returns (SessionSig.DecodedSignature memory, bool hasBlacklist) {
+ return SessionSig.recoverConfiguration(encoded);
+ }
+
+}
+
+contract SessionSigTest is SessionTestBase {
+
+ SessionSigHarness internal harness;
+ Vm.Wallet internal sessionWallet;
+ Vm.Wallet internal identityWallet;
+
+ function setUp() public {
+ harness = new SessionSigHarness();
+ sessionWallet = vm.createWallet("session");
+ identityWallet = vm.createWallet("identity");
+ }
+
+ function testHashCallCollision(
+ uint256 chainId,
+ Payload.Decoded memory payload1,
+ Payload.Decoded memory payload2
+ ) public {
+ vm.assume(payload1.calls.length > 0);
+ vm.assume(payload2.calls.length > 0);
+ chainId = bound(chainId, 1, 2 ** 26 - 1);
+ vm.chainId(chainId);
+
+ uint256 maxCalls = 10;
+
+ if (payload1.calls.length > maxCalls) {
+ Payload.Call[] memory payload1Calls = payload1.calls;
+ assembly {
+ mstore(payload1Calls, maxCalls)
+ }
+ payload1.calls = payload1Calls;
+ }
+
+ if (payload2.calls.length > maxCalls) {
+ Payload.Call[] memory payload2Calls = payload2.calls;
+ assembly {
+ mstore(payload2Calls, maxCalls)
+ }
+ payload2.calls = payload2Calls;
+ }
+
+ for (uint256 i = 0; i < payload1.calls.length; i++) {
+ Payload.Call memory call1 = payload1.calls[i];
+ for (uint256 j = 0; j < payload2.calls.length; j++) {
+ Payload.Call memory call2 = payload2.calls[j];
+
+ if (
+ i == j && call1.to == call2.to && keccak256(call1.data) == keccak256(call2.data)
+ && call1.gasLimit == call2.gasLimit && call1.delegateCall == call2.delegateCall
+ && call1.onlyFallback == call2.onlyFallback && call1.behaviorOnError == call2.behaviorOnError
+ && payload1.space == payload2.space && payload1.nonce == payload2.nonce
+ && payload1.noChainId == payload2.noChainId
+ ) {
+ // The allowed collision case
+ continue;
+ }
+
+ bytes32 callHash1 = SessionSig.hashCallWithReplayProtection(payload1, i);
+ bytes32 callHash2 = SessionSig.hashCallWithReplayProtection(payload2, j);
+ assertNotEq(callHash1, callHash2, "Call hashes should be different");
+ }
+ }
+ }
+
+ function testSingleExplicitSignature(
+ bool useChainId
+ ) public {
+ Payload.Decoded memory payload = _buildPayload(1);
+ {
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: useChainId ? block.chainid : 0,
+ valueLimit: 1000,
+ deadline: 2000,
+ permissions: new Permission[](1)
+ });
+ {
+ sessionPerms.permissions[0] = Permission({ target: address(0xBEEF), rules: new ParameterRule[](1) });
+ sessionPerms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(0),
+ offset: 0,
+ mask: bytes32(0)
+ });
+ }
+
+ // Create the topology from the CLI.
+ string memory topology;
+ {
+ topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ }
+
+ // Sign the payload.
+ string memory callSignature;
+ {
+ uint8 permissionIdx = 0;
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload, 0);
+ string memory sessionSignature = _signAndEncodeRSV(callHash, sessionWallet);
+ callSignature = _explicitCallSignatureToJSON(permissionIdx, sessionSignature);
+ }
+
+ // Construct the encoded signature.
+ bytes memory encoded;
+ {
+ string[] memory callSignatures = new string[](1);
+ callSignatures[0] = callSignature;
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ }
+
+ // Recover and validate.
+ {
+ SessionSig.DecodedSignature memory sig = harness.recover(payload, encoded);
+ assertEq(sig.callSignatures.length, 1, "Call signatures length");
+ SessionSig.CallSignature memory callSig = sig.callSignatures[0];
+ assertFalse(callSig.isImplicit, "Call should be explicit");
+ assertEq(callSig.sessionSigner, sessionWallet.addr, "Recovered session signer");
+ assertEq(sig.implicitBlacklist.length, 0, "Blacklist should be empty");
+ assertEq(sig.sessionPermissions.length, 1, "Session permissions length");
+ assertEq(sig.sessionPermissions[0].signer, sessionWallet.addr, "Session permission signer");
+
+ bytes32 imageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+ assertEq(sig.imageHash, imageHash, "Image hash");
+ }
+ }
+
+ function testSingleImplicitSignature(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ Payload.Decoded memory payload = _buildPayload(1);
+ {
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+
+ // Sign the payload.
+ string memory callSignature = _createImplicitCallSignature(payload, 0, sessionWallet, identityWallet, attestation);
+
+ // Create the topology from the CLI.
+ string memory topology;
+ {
+ topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ }
+
+ // Create the encoded signature.
+ bytes memory encoded;
+ {
+ string[] memory callSignatures = new string[](1);
+ callSignatures[0] = callSignature;
+ address[] memory explicitSigners = new address[](0);
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ }
+
+ // Recover and validate.
+ {
+ SessionSig.DecodedSignature memory sig = harness.recover(payload, encoded);
+ assertEq(sig.callSignatures.length, 1, "Call signatures length");
+ SessionSig.CallSignature memory callSig = sig.callSignatures[0];
+ assertTrue(callSig.isImplicit, "Call should be implicit");
+ assertEq(callSig.attestation.approvedSigner, sessionWallet.addr, "Recovered attestation signer");
+ assertEq(sig.implicitBlacklist.length, 0, "Blacklist should be empty");
+ assertEq(sig.sessionPermissions.length, 0, "Session permissions should be empty");
+
+ bytes32 imageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+ assertEq(sig.imageHash, imageHash, "Image hash");
+ }
+ }
+
+ function testMultipleImplicitSignatures(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ Payload.Decoded memory payload = _buildPayload(2);
+ {
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test1",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ payload.calls[1] = Payload.Call({
+ to: address(0xCAFE),
+ value: 456,
+ data: "test2",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+
+ // Create attestations and signatures for both calls
+ string[] memory callSignatures = new string[](2);
+ {
+ callSignatures[0] = _createImplicitCallSignature(payload, 0, sessionWallet, identityWallet, attestation);
+ callSignatures[1] = _createImplicitCallSignature(payload, 1, sessionWallet, identityWallet, attestation);
+ }
+
+ // Create the topology
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+
+ // Create the encoded signature
+ bytes memory encoded;
+ {
+ address[] memory explicitSigners = new address[](0);
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ }
+
+ // Recover and validate
+ {
+ SessionSig.DecodedSignature memory sig = harness.recover(payload, encoded);
+ assertEq(sig.callSignatures.length, 2, "Call signatures length");
+
+ for (uint256 i = 0; i < sig.callSignatures.length; i++) {
+ SessionSig.CallSignature memory callSig = sig.callSignatures[i];
+ assertTrue(callSig.isImplicit, "Call should be implicit");
+ assertEq(callSig.attestation.approvedSigner, sessionWallet.addr, "Recovered attestation signer");
+ }
+
+ assertEq(sig.implicitBlacklist.length, 0, "Blacklist should be empty");
+ assertEq(sig.sessionPermissions.length, 0, "Session permissions should be empty");
+
+ bytes32 imageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+ assertEq(sig.imageHash, imageHash, "Image hash");
+ }
+ }
+
+ function testMultipleExplicitSignatures(
+ bool useChainId
+ ) public {
+ // Create a second session wallet
+ Vm.Wallet memory sessionWallet2 = vm.createWallet("session2");
+
+ Payload.Decoded memory payload = _buildPayload(2);
+ {
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test1",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ payload.calls[1] = Payload.Call({
+ to: address(0xCAFE),
+ value: 456,
+ data: "test2",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+
+ // Create session permissions for both calls with different signers
+ SessionPermissions[] memory sessionPermsArray = new SessionPermissions[](2);
+ {
+ sessionPermsArray[0] =
+ _createSessionPermissions(address(0xBEEF), useChainId ? block.chainid : 0, 1000, 2000, sessionWallet.addr);
+ sessionPermsArray[1] =
+ _createSessionPermissions(address(0xCAFE), useChainId ? block.chainid : 0, 1000, 2000, sessionWallet2.addr);
+ }
+
+ // Create the topology from the CLI
+ string memory topology;
+ {
+ topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ for (uint256 i = 0; i < sessionPermsArray.length; i++) {
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPermsArray[i]);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ }
+ }
+
+ // Sign the payloads and create call signatures with different signers
+ string[] memory callSignatures = new string[](2);
+ {
+ // First call signed by sessionWallet
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload, 0);
+ string memory sessionSignature1 = _signAndEncodeRSV(callHash, sessionWallet);
+ callSignatures[0] = _explicitCallSignatureToJSON(0, sessionSignature1);
+
+ // Second call signed by sessionWallet2
+ callHash = SessionSig.hashCallWithReplayProtection(payload, 1);
+ string memory sessionSignature2 = _signAndEncodeRSV(callHash, sessionWallet2);
+ callSignatures[1] = _explicitCallSignatureToJSON(1, sessionSignature2);
+ }
+
+ // Construct the encoded signature
+ bytes memory encoded;
+ {
+ address[] memory explicitSigners = new address[](2);
+ explicitSigners[0] = sessionWallet.addr;
+ explicitSigners[1] = sessionWallet2.addr;
+ address[] memory implicitSigners = new address[](0);
+ encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ }
+
+ // Recover and validate
+ {
+ SessionSig.DecodedSignature memory sig = harness.recover(payload, encoded);
+ assertEq(sig.callSignatures.length, 2, "Call signatures length");
+
+ // Verify first signature
+ assertFalse(sig.callSignatures[0].isImplicit, "First call should be explicit");
+ assertEq(sig.callSignatures[0].sessionSigner, sessionWallet.addr, "First session signer");
+
+ // Verify second signature
+ assertFalse(sig.callSignatures[1].isImplicit, "Second call should be explicit");
+ assertEq(sig.callSignatures[1].sessionSigner, sessionWallet2.addr, "Second session signer");
+
+ assertEq(sig.implicitBlacklist.length, 0, "Blacklist should be empty");
+ assertEq(sig.sessionPermissions.length, 2, "Session permissions length");
+ bool found0 = false;
+ bool found1 = false;
+ for (uint256 i = 0; i < sig.sessionPermissions.length; i++) {
+ if (sig.sessionPermissions[i].signer == sessionWallet.addr) {
+ found0 = true;
+ }
+ if (sig.sessionPermissions[i].signer == sessionWallet2.addr) {
+ found1 = true;
+ }
+ }
+ assertTrue(found0, "Session permission signer 0 not found");
+ assertTrue(found1, "Session permission signer 1 not found");
+
+ bytes32 imageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+ assertEq(sig.imageHash, imageHash, "Image hash");
+ }
+ }
+
+ function testRecover_invalidSessionSigner(
+ bool useChainId
+ ) public {
+ Payload.Decoded memory payload = _buildPayload(1);
+ {
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: useChainId ? block.chainid : 0,
+ valueLimit: 1000,
+ deadline: 2000,
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(0xBEEF), rules: new ParameterRule[](0) });
+
+ // Create the topology from the CLI.
+ string memory topology;
+ {
+ topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ }
+
+ // Generate an invalid session signature
+ string memory sessionSignature =
+ "0x0000000000000000000000000000000000000000000000000000000000000000:0x0000000000000000000000000000000000000000000000000000000000000000:0";
+ string memory callSignature = _explicitCallSignatureToJSON(0, sessionSignature);
+
+ // Construct the encoded signature.
+ bytes memory encoded;
+ {
+ string[] memory callSignatures = new string[](1);
+ callSignatures[0] = callSignature;
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ }
+
+ // Recover and validate.
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidSessionSigner.selector, address(0)));
+ harness.recover(payload, encoded);
+ }
+
+ function testRecover_invalidIdentitySigner_unset() public {
+ // Create a topology with an invalid identity signer
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, address(0));
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create a call signature
+ bytes memory encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, new string[](0), new address[](0), new address[](0));
+
+ // Recover the signature
+ vm.expectRevert(SessionErrors.InvalidIdentitySigner.selector);
+ harness.recover(payload, encoded);
+ }
+
+ function testRecover_invalidIdentitySigner_noMatchAttestationSigner(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ // Create a topology with an invalid identity signer
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ Vm.Wallet memory attestationWallet = vm.createWallet("attestation");
+
+ // Sign the payload.
+ string memory callSignature =
+ _createImplicitCallSignature(payload, 0, sessionWallet, attestationWallet, attestation);
+
+ // Create a call signature
+ string[] memory callSignatures = new string[](1);
+ callSignatures[0] = callSignature;
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ bytes memory encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, new address[](0), implicitSigners);
+
+ // Recover the signature
+ vm.expectRevert(SessionErrors.InvalidIdentitySigner.selector);
+ harness.recover(payload, encoded);
+ }
+
+ function testRecover_invalidIdentitySigner_noSignersEncoded(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ // Create a topology with an invalid identity signer
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, address(0));
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ Vm.Wallet memory attestationWallet = vm.createWallet("attestation");
+
+ // Sign the payload.
+ string memory callSignature =
+ _createImplicitCallSignature(payload, 0, sessionWallet, attestationWallet, attestation);
+
+ // Create a call signature
+ string[] memory callSignatures = new string[](1);
+ callSignatures[0] = callSignature;
+ bytes memory encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, new address[](0), new address[](0));
+
+ // Recover the signature
+ vm.expectRevert(SessionErrors.InvalidIdentitySigner.selector);
+ harness.recover(payload, encoded);
+ }
+
+ function testRecover_invalidBlacklist_requiredForImplicitSigner(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation.authData.issuedAt = uint64(bound(attestation.authData.issuedAt, 0, block.timestamp));
+
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Call encodeCallSignatures with empty call signatures to encode the topology
+ bytes memory encodedTopologyWithSize =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, new string[](0), new address[](0), new address[](0));
+ assertGt(encodedTopologyWithSize.length, 4, "Encoded signature should not be empty");
+
+ // Strip the last byte (attestation count)
+ bytes memory encoded = new bytes(encodedTopologyWithSize.length - 1);
+ for (uint256 i = 0; i < encoded.length; i++) {
+ encoded[i] = encodedTopologyWithSize[i];
+ }
+
+ // Encode the attestation and signature
+ bytes32 attestationHash = attestation.toHash();
+ bytes memory compactSignature = signRSVCompact(attestationHash, identityWallet);
+ encoded = abi.encodePacked(encoded, uint8(1), LibAttestation.toPacked(attestation), compactSignature);
+
+ // We don't bother encoding the call signatures as will fail before then
+
+ // Recover the signature
+ vm.expectRevert(SessionErrors.InvalidBlacklist.selector);
+ harness.recover(payload, encoded);
+ }
+
+ function testRecover_invalidAttestationIndex(Attestation memory attestation, uint256 count, uint256 index) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ attestation.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ count = bound(count, 1, 10);
+ index = bound(index, count + 1, type(uint8).max / 2); // /2 as top bit used in flag
+
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Call encodeCallSignatures with empty call signatures to encode the topology
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ bytes memory encodedTopologyWithSize =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, new string[](0), new address[](0), implicitSigners);
+ assertGt(encodedTopologyWithSize.length, 4, "Encoded signature should not be empty");
+
+ // Strip the last byte (attestation count)
+ bytes memory encoded = new bytes(encodedTopologyWithSize.length - 1);
+ for (uint256 i = 0; i < encoded.length; i++) {
+ encoded[i] = encodedTopologyWithSize[i];
+ }
+
+ // Encode the attestations and signatures
+ bytes32 attestationHash = attestation.toHash();
+ bytes memory compactSignature = signRSVCompact(attestationHash, identityWallet);
+ encoded = abi.encodePacked(encoded, uint8(count));
+ for (uint256 i = 0; i < count; i++) {
+ encoded = abi.encodePacked(encoded, LibAttestation.toPacked(attestation), compactSignature);
+ }
+
+ // Encode the call signature with invalid index
+ uint8 implicitFlag = uint8(index | 0x80);
+ encoded = abi.encodePacked(encoded, implicitFlag);
+ // Ignore encoding the signature as will fail before then
+
+ // Recover the signature
+ vm.expectRevert(SessionErrors.InvalidAttestation.selector);
+ harness.recover(payload, encoded);
+ }
+
+ function testConfiguration_largeBlacklist(
+ address[] memory blacklist
+ ) public {
+ vm.assume(blacklist.length > 0);
+ if (blacklist.length < 0x0f) {
+ address[] memory largerBlacklist = new address[](0x0f);
+ for (uint256 i = 0; i < largerBlacklist.length; i++) {
+ largerBlacklist[i] = blacklist[i % blacklist.length];
+ }
+ blacklist = largerBlacklist;
+ } else if (blacklist.length > 0xff) {
+ // Truncate size to max 0xff
+ assembly {
+ mstore(blacklist, 0xff)
+ }
+ }
+
+ // Remove duplicates
+ {
+ address[] memory uniqueBlacklist = new address[](blacklist.length);
+ uint256 uniqueBlacklistIndex = 0;
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ bool found = false;
+ for (uint256 j = 0; j < uniqueBlacklistIndex; j++) {
+ if (blacklist[i] == uniqueBlacklist[j]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ uniqueBlacklist[uniqueBlacklistIndex++] = blacklist[i];
+ }
+ }
+ blacklist = uniqueBlacklist;
+ assembly {
+ mstore(blacklist, uniqueBlacklistIndex)
+ }
+ }
+
+ // Create a topology
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ topology = PrimitivesRPC.sessionImplicitAddBlacklistAddress(vm, topology, blacklist[i]);
+ }
+
+ // Call encodeCallSignatures with empty call signatures to encode the topology
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ bytes memory encoded = PrimitivesRPC.sessionEncodeTopology(vm, topology);
+
+ // Recover the configuration
+ (SessionSig.DecodedSignature memory sig, bool hasBlacklist) = harness.recoverConfiguration(encoded);
+ assertEq(sig.implicitBlacklist.length, blacklist.length, "Implicit blacklist length");
+ assertEq(hasBlacklist, true, "Blacklist should be present");
+ }
+
+ function testConfiguration_duplicateBlacklistNodes(
+ address[5] memory fiveBlacklists,
+ uint8 size
+ ) public {
+ size = uint8(bound(size, 0, 5));
+ address[] memory blacklist = new address[](size);
+ for (uint256 i = 0; i < size; i++) {
+ blacklist[i] = fiveBlacklists[i];
+ }
+
+ _sortAddressesMemory(blacklist);
+
+ bytes memory encoded = new bytes(0);
+ for (uint256 i = 0; i < 2; i++) {
+ // Flag is top 4 bits 0x03, lower 4 bits are blacklist count
+ uint8 blacklistFlag = uint8(0x30) | uint8(blacklist.length);
+ encoded = abi.encodePacked(encoded, blacklistFlag);
+ for (uint256 j = 0; j < blacklist.length; j++) {
+ encoded = abi.encodePacked(encoded, blacklist[j]);
+ }
+ }
+
+ // Recover the configuration
+ vm.expectRevert(SessionErrors.InvalidBlacklist.selector);
+ harness.recoverConfiguration(encoded);
+ }
+
+ function testConfiguration_duplicateBlacklistNodes_inBranch(
+ address[5] memory fiveBlacklists,
+ uint8 size
+ ) public {
+ size = uint8(bound(size, 0, 5));
+ address[] memory blacklist = new address[](size);
+ for (uint256 i = 0; i < size; i++) {
+ blacklist[i] = fiveBlacklists[i];
+ }
+
+ _sortAddressesMemory(blacklist);
+
+ bytes memory encoded = new bytes(0);
+ // Blacklist encoding
+ bytes memory blacklistEncoded = new bytes(0);
+ uint8 blacklistFlag = uint8(0x30) | uint8(blacklist.length);
+ blacklistEncoded = abi.encodePacked(blacklistEncoded, blacklistFlag);
+ for (uint256 j = 0; j < blacklist.length; j++) {
+ blacklistEncoded = abi.encodePacked(blacklistEncoded, blacklist[j]);
+ }
+
+ // Branch encoding
+ uint8 branchSize = uint8(blacklistEncoded.length);
+ uint8 branchFlag = uint8(0x21);
+ encoded = abi.encodePacked(encoded, branchFlag, branchSize, blacklistEncoded);
+
+ // Two of these branches
+ encoded = abi.encodePacked(encoded, encoded);
+
+ // Recover the configuration
+ vm.expectRevert(SessionErrors.InvalidBlacklist.selector);
+ harness.recoverConfiguration(encoded);
+ }
+
+ function testConfiguration_duplicateIdentityNodes(address identitySigner1, address identitySigner2) public {
+ vm.assume(identitySigner1 != address(0));
+ vm.assume(identitySigner2 != address(0));
+
+ bytes memory encoded = abi.encodePacked(uint8(0x40), identitySigner1);
+ encoded = abi.encodePacked(encoded, uint8(0x40), identitySigner2);
+
+ // Recover the configuration
+ vm.expectRevert(SessionErrors.InvalidIdentitySigner.selector);
+ harness.recoverConfiguration(encoded);
+ }
+
+ function testConfiguration_duplicateIdentityNodes_inBranch(
+ address identitySigner
+ ) public {
+ vm.assume(identitySigner != address(0));
+
+ // Identity signer encoding
+ bytes memory identityEncoded = abi.encodePacked(uint8(0x40), identitySigner);
+
+ // Branch encoding
+ uint8 branchSize = uint8(identityEncoded.length);
+ uint8 branchFlag = uint8(0x21);
+ bytes memory encoded = abi.encodePacked(branchFlag, branchSize, identityEncoded);
+
+ // Two of these branches
+ encoded = abi.encodePacked(encoded, encoded);
+
+ // Recover the configuration
+ vm.expectRevert(SessionErrors.InvalidIdentitySigner.selector);
+ harness.recoverConfiguration(encoded);
+ }
+
+ function testConfiguration_invalidNode(
+ uint8 invalidNodeFlag
+ ) public {
+ invalidNodeFlag = uint8(bound(invalidNodeFlag, 0x05, 0x0f));
+
+ bytes memory encoded = abi.encodePacked(invalidNodeFlag << 4);
+
+ // Recover the configuration
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidNodeType.selector, invalidNodeFlag));
+ harness.recoverConfiguration(encoded);
+ }
+
+ function testLargeTopology(
+ address[] memory explicitSigners,
+ uint256 signersIncludeCount,
+ bool includeImplicitSigner,
+ address[] memory implicitBlacklist
+ ) public {
+ _sortAddressesMemory(implicitBlacklist);
+
+ // Reduce size to max 20
+ if (explicitSigners.length > 20) {
+ assembly {
+ mstore(explicitSigners, 20)
+ }
+ }
+ for (uint256 i = 0; i < explicitSigners.length; i++) {
+ vm.assume(explicitSigners[i] != address(0));
+ // Ensure there are no duplicates.
+ for (uint256 j = 0; j < explicitSigners.length; j++) {
+ if (i != j) {
+ vm.assume(explicitSigners[i] != explicitSigners[j]);
+ }
+ }
+ }
+ if (implicitBlacklist.length > 5) {
+ assembly {
+ mstore(implicitBlacklist, 5)
+ }
+ }
+ // Ensure no duplicates for the implicit blacklist
+ for (uint256 i = 0; i < implicitBlacklist.length; i++) {
+ for (uint256 j = 0; j < implicitBlacklist.length; j++) {
+ if (i != j) {
+ vm.assume(implicitBlacklist[i] != implicitBlacklist[j]);
+ }
+ }
+ }
+ signersIncludeCount = bound(signersIncludeCount, 0, explicitSigners.length);
+
+ // Add session permissions and blacklist to the topology
+ SessionPermissions memory sessionPerms;
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ for (uint256 i = 0; i < explicitSigners.length; i++) {
+ sessionPerms.signer = explicitSigners[i];
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ }
+ for (uint256 i = 0; i < implicitBlacklist.length; i++) {
+ topology = PrimitivesRPC.sessionImplicitAddBlacklistAddress(vm, topology, implicitBlacklist[i]);
+ }
+
+ // Set signers to include in the configuration
+ assembly {
+ mstore(explicitSigners, signersIncludeCount)
+ }
+ address[] memory implicitSigners = new address[](includeImplicitSigner ? 1 : 0);
+ if (includeImplicitSigner) {
+ implicitSigners[0] = sessionWallet.addr;
+ }
+ // Call encodeCallSignatures with empty call signatures to encode the topology (minimised)
+ bytes memory encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, new string[](0), explicitSigners, implicitSigners);
+ assertGt(encoded.length, 4, "Encoded signature should not be empty");
+
+ // Strip the first 3 bytes (size), and last byte (attestation count)
+ bytes memory encodedWithoutSize = new bytes(encoded.length - 4);
+ for (uint256 i = 0; i < encodedWithoutSize.length; i++) {
+ encodedWithoutSize[i] = encoded[i + 3];
+ }
+
+ // Recover the configuration
+ (SessionSig.DecodedSignature memory sig, bool hasBlacklist) = harness.recoverConfiguration(encodedWithoutSize);
+ assertEq(sig.identitySigner, identityWallet.addr, "Identity signer");
+ assertEq(sig.sessionPermissions.length, explicitSigners.length, "Session permissions length"); // Truncated list
+ for (uint256 i = 0; i < explicitSigners.length; i++) {
+ bool found = false;
+ for (uint256 j = 0; j < sig.sessionPermissions.length; j++) {
+ if (sig.sessionPermissions[j].signer == explicitSigners[i]) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found, "Session permission signer not found");
+ }
+ if (includeImplicitSigner) {
+ assertEq(hasBlacklist, includeImplicitSigner, "Blacklist not included with implicit signer");
+ assertEq(sig.implicitBlacklist.length, implicitBlacklist.length, "Implicit blacklist length");
+ for (uint256 i = 0; i < implicitBlacklist.length; i++) {
+ bool found = false;
+ for (uint256 j = 0; j < sig.implicitBlacklist.length; j++) {
+ if (sig.implicitBlacklist[j] == implicitBlacklist[i]) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue(found, "Implicit blacklist address not found");
+ }
+ }
+ }
+
+ function testAttestationOptimisation(Attestation memory attestation1, Attestation memory attestation2) public {
+ // Create a second session wallet
+ Vm.Wallet memory sessionWallet2 = vm.createWallet("session2");
+
+ attestation1.approvedSigner = sessionWallet.addr;
+ attestation2.approvedSigner = sessionWallet2.addr;
+ attestation1.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+ attestation2.authData.redirectUrl = "https://example.com"; // Normalise for safe JSONify
+
+ // Create a payload with 2 calls
+ Payload.Decoded memory payload = _buildPayload(2);
+ {
+ payload.calls[0] = Payload.Call({
+ to: address(0xBEEF),
+ value: 123,
+ data: "test1",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ payload.calls[1] = Payload.Call({
+ to: address(0xCAFE),
+ value: 456,
+ data: "test2",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+ }
+
+ // Create 2 call signatures for the same session wallet and attestation
+ string memory callSignatureA = _createImplicitCallSignature(payload, 0, sessionWallet, identityWallet, attestation1);
+ string memory callSignatureB = _createImplicitCallSignature(payload, 1, sessionWallet, identityWallet, attestation1);
+
+ // Create the second call signature for the second session wallet and attestation
+ string memory callSignatureC =
+ _createImplicitCallSignature(payload, 1, sessionWallet2, identityWallet, attestation2);
+
+ // Create a topology
+ string memory topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+
+ // Encode the call signatures for single session wallet
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = sessionWallet.addr;
+ string[] memory callSignatures = new string[](2);
+ callSignatures[0] = callSignatureA;
+ callSignatures[1] = callSignatureB;
+ bytes memory encoded =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, new address[](0), implicitSigners);
+
+ // Encode the call signatures for both session wallets
+ implicitSigners = new address[](2);
+ implicitSigners[0] = sessionWallet.addr;
+ implicitSigners[1] = sessionWallet2.addr;
+ callSignatures = new string[](2);
+ callSignatures[0] = callSignatureA;
+ callSignatures[1] = callSignatureC;
+ bytes memory encoded2 =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, new address[](0), implicitSigners);
+
+ // Ensure the length of the calldata has been optimised when reusing the same attestation
+ assertLt(
+ encoded.length, encoded2.length, "Encoded call signatures should be shorter when reusing the same attestation"
+ );
+ }
+
+ function testEmptyPermissionsStructSize_direct(
+ address signer,
+ uint256 chainId,
+ uint256 valueLimit,
+ uint64 deadline
+ ) public view {
+ // Create an empty permissions struct
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: signer,
+ chainId: chainId,
+ valueLimit: valueLimit,
+ deadline: deadline,
+ permissions: new Permission[](0)
+ });
+
+ // Directly encode the permissions struct
+ bytes memory encoded = abi.encodePacked(
+ uint8(SessionSig.FLAG_PERMISSIONS),
+ sessionPerms.signer,
+ sessionPerms.chainId,
+ sessionPerms.valueLimit,
+ sessionPerms.deadline,
+ uint8(0) // empty permissions array length
+ );
+
+ // Verify the size is the minimum size
+ assertEq(encoded.length, SessionSig.MIN_ENCODED_PERMISSION_SIZE, "Incorrect size for empty permissions struct");
+
+ // Verify we can decode it back
+ (SessionSig.DecodedSignature memory sig,) = harness.recoverConfiguration(encoded);
+ assertEq(sig.sessionPermissions.length, 1, "Should have one permissions struct");
+ assertEq(sig.sessionPermissions[0].signer, signer, "Signer should match");
+ assertEq(sig.sessionPermissions[0].chainId, chainId, "Chain ID should match");
+ assertEq(sig.sessionPermissions[0].valueLimit, valueLimit, "Value limit should match");
+ assertEq(sig.sessionPermissions[0].deadline, deadline, "Deadline should match");
+ assertEq(sig.sessionPermissions[0].permissions.length, 0, "Should have no permissions");
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionTestBase.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionTestBase.sol
new file mode 100644
index 000000000..8a1ecb703
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/SessionTestBase.sol
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Test, Vm } from "forge-std/Test.sol";
+
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+import { AdvTest } from "test/utils/TestUtils.sol";
+
+import { SessionManager } from "src/extensions/sessions/SessionManager.sol";
+import { SessionSig } from "src/extensions/sessions/SessionSig.sol";
+import { SessionPermissions } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import { ParameterOperation, ParameterRule, Permission } from "src/extensions/sessions/explicit/Permission.sol";
+
+import { Attestation, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+abstract contract SessionTestBase is AdvTest {
+
+ using LibAttestation for Attestation;
+
+ address internal constant VALUE_TRACKING_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
+
+ function _signAndEncodeRSV(bytes32 hash, Vm.Wallet memory wallet) internal pure returns (string memory) {
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(wallet.privateKey, hash);
+ return string(abi.encodePacked(vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)));
+ }
+
+ /// @dev Helper to build a Payload.Decoded with a given number of calls.
+ function _buildPayload(
+ uint256 callCount
+ ) internal pure returns (Payload.Decoded memory payload) {
+ payload.kind = Payload.KIND_TRANSACTIONS;
+ payload.noChainId = true;
+ payload.space = 0;
+ payload.nonce = 0;
+ payload.parentWallets = new address[](0);
+ payload.calls = new Payload.Call[](callCount);
+ }
+
+ function _sessionPermissionsToJSON(
+ SessionPermissions memory sessionPerms
+ ) internal pure returns (string memory) {
+ string memory json = '{"signer":"';
+ json = string.concat(json, vm.toString(sessionPerms.signer));
+ json = string.concat(json, '","chainId":"');
+ json = string.concat(json, vm.toString(sessionPerms.chainId));
+ json = string.concat(json, '","valueLimit":"');
+ json = string.concat(json, vm.toString(sessionPerms.valueLimit));
+ json = string.concat(json, '","deadline":"');
+ json = string.concat(json, vm.toString(sessionPerms.deadline));
+ json = string.concat(json, '","permissions":[');
+ for (uint256 i = 0; i < sessionPerms.permissions.length; i++) {
+ if (i > 0) {
+ json = string.concat(json, ",");
+ }
+ json = string.concat(json, _permissionToJSON(sessionPerms.permissions[i]));
+ }
+ json = string.concat(json, "]}");
+ return json;
+ }
+
+ function _permissionToJSON(
+ Permission memory permission
+ ) internal pure returns (string memory) {
+ string memory json = '{"target":"';
+ json = string.concat(json, vm.toString(permission.target));
+ json = string.concat(json, '","rules":[');
+ for (uint256 i = 0; i < permission.rules.length; i++) {
+ if (i > 0) {
+ json = string.concat(json, ",");
+ }
+ json = string.concat(json, _ruleToJSON(permission.rules[i]));
+ }
+ json = string.concat(json, "]}");
+ return json;
+ }
+
+ function _ruleToJSON(
+ ParameterRule memory rule
+ ) internal pure returns (string memory) {
+ string memory json = '{"cumulative":';
+ json = string.concat(json, vm.toString(rule.cumulative));
+ json = string.concat(json, ',"operation":');
+ json = string.concat(json, vm.toString(uint8(rule.operation)));
+ json = string.concat(json, ',"value":"');
+ json = string.concat(json, vm.toString(rule.value));
+ json = string.concat(json, '","offset":"');
+ json = string.concat(json, vm.toString(rule.offset));
+ json = string.concat(json, '","mask":"');
+ json = string.concat(json, vm.toString(rule.mask));
+ json = string.concat(json, '"}');
+ return json;
+ }
+
+ function _attestationToJSON(
+ Attestation memory attestation
+ ) internal pure returns (string memory) {
+ string memory json = '{"approvedSigner":"';
+ json = string.concat(json, vm.toString(attestation.approvedSigner));
+ json = string.concat(json, '","identityType":"');
+ json = string.concat(json, vm.toString(attestation.identityType));
+ json = string.concat(json, '","issuerHash":"');
+ json = string.concat(json, vm.toString(attestation.issuerHash));
+ json = string.concat(json, '","audienceHash":"');
+ json = string.concat(json, vm.toString(attestation.audienceHash));
+ json = string.concat(json, '","authData":{"redirectUrl":"');
+ json = string.concat(json, attestation.authData.redirectUrl);
+ json = string.concat(json, '","issuedAt":"');
+ json = string.concat(json, vm.toString(attestation.authData.issuedAt));
+ json = string.concat(json, '"},"applicationData":"');
+ json = string.concat(json, vm.toString(attestation.applicationData));
+ json = string.concat(json, '"}');
+ return json;
+ }
+
+ function _createImplicitCallSignature(
+ Payload.Decoded memory payload,
+ uint256 callIdx,
+ Vm.Wallet memory signer,
+ Vm.Wallet memory identitySigner,
+ Attestation memory attestation
+ ) internal view returns (string memory) {
+ bytes32 attestationHash = attestation.toHash();
+ string memory identitySignature = _signAndEncodeRSV(attestationHash, identitySigner);
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload, callIdx);
+ string memory sessionSignature = _signAndEncodeRSV(callHash, signer);
+ return _implicitCallSignatureToJSON(attestation, sessionSignature, identitySignature);
+ }
+
+ function _implicitCallSignatureToJSON(
+ Attestation memory attestation,
+ string memory sessionSignature,
+ string memory identitySignature
+ ) internal pure returns (string memory) {
+ string memory json = '{"attestation":';
+ json = string.concat(json, _attestationToJSON(attestation));
+ json = string.concat(json, ',"sessionSignature":"');
+ json = string.concat(json, sessionSignature);
+ json = string.concat(json, '","identitySignature":"');
+ json = string.concat(json, identitySignature);
+ json = string.concat(json, '"}');
+ return json;
+ }
+
+ function _explicitCallSignatureToJSON(
+ uint8 permissionIndex,
+ string memory sessionSignature
+ ) internal pure returns (string memory) {
+ string memory json = '{"permissionIndex":"';
+ json = string.concat(json, vm.toString(permissionIndex));
+ json = string.concat(json, '","sessionSignature":"');
+ json = string.concat(json, sessionSignature);
+ json = string.concat(json, '"}');
+ return json;
+ }
+
+ function _createSessionPermissions(
+ address target,
+ uint256 chainId,
+ uint256 valueLimit,
+ uint64 deadline,
+ address signer
+ ) internal pure returns (SessionPermissions memory) {
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: signer,
+ chainId: chainId,
+ valueLimit: valueLimit,
+ deadline: deadline,
+ permissions: new Permission[](1)
+ });
+
+ sessionPerms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](1) });
+ sessionPerms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(0),
+ offset: 0,
+ mask: bytes32(0)
+ });
+
+ return sessionPerms;
+ }
+
+ // Convert a single SessionPermissions struct into an array.
+ function _toArray(
+ SessionPermissions memory perm
+ ) internal pure returns (SessionPermissions[] memory) {
+ SessionPermissions[] memory arr = new SessionPermissions[](1);
+ arr[0] = perm;
+ return arr;
+ }
+
+ /// @notice Sorts an array of addresses in memory.
+ /// @param addresses The array of addresses to sort.
+ function _sortAddressesMemory(
+ address[] memory addresses
+ ) internal pure {
+ // Sort the addresses using bubble sort.
+ for (uint256 i = 0; i < addresses.length; i++) {
+ for (uint256 j = 0; j < addresses.length - i - 1; j++) {
+ if (addresses[j] > addresses[j + 1]) {
+ address temp = addresses[j];
+ addresses[j] = addresses[j + 1];
+ addresses[j + 1] = temp;
+ }
+ }
+ }
+ }
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/explicit/ExplicitSessionManager.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/explicit/ExplicitSessionManager.t.sol
new file mode 100644
index 000000000..c1e8784fa
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/explicit/ExplicitSessionManager.t.sol
@@ -0,0 +1,866 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Vm } from "forge-std/Test.sol";
+import { SessionTestBase } from "test/extensions/sessions/SessionTestBase.sol";
+
+import { SessionErrors } from "src/extensions/sessions/SessionErrors.sol";
+import { ExplicitSessionManager } from "src/extensions/sessions/explicit/ExplicitSessionManager.sol";
+import { IExplicitSessionManager } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import { SessionPermissions, SessionUsageLimits } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+contract ExplicitSessionManagerTest is SessionTestBase {
+
+ ExplicitSessionManagerHarness harness;
+ address wallet;
+ Vm.Wallet sessionWallet;
+ bytes32 constant SELECTOR_MASK = bytes32(bytes4(0xffffffff));
+
+ modifier supportChainId(
+ uint64 chainId
+ ) {
+ if (chainId != 0) {
+ vm.chainId(chainId);
+ }
+ _;
+ }
+
+ function setUp() public {
+ harness = new ExplicitSessionManagerHarness();
+ wallet = vm.createWallet("wallet").addr;
+ sessionWallet = vm.createWallet("session");
+ }
+
+ function test_validateExplicitCall(
+ uint64 chainId,
+ address target,
+ bytes4 selector,
+ bytes memory callData
+ ) public supportChainId(chainId) {
+ vm.assume(target != address(harness));
+ // Build a payload with one call.
+ Payload.Decoded memory payload = _buildPayload(1);
+ // Prepend the selector to the call data.
+ callData = abi.encodePacked(selector, callData);
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create SessionPermissions with one Permission.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: 0, // no native token usage for this test
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ // Allow calls to the target if the selector matches..
+ perms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](1) });
+ perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(selector),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ // Prepare initial session usage limits.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ // Convert our single SessionPermissions into an array.
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ // Call the internal explicit call validator.
+ SessionUsageLimits memory newUsage = harness.validateExplicitCall(
+ payload,
+ 0, // call index
+ wallet,
+ sessionWallet.addr,
+ permsArr,
+ 0, // permission index
+ usage
+ );
+
+ // Since the call value is 0, expect totalValueUsed to remain 0.
+ assertEq(newUsage.totalValueUsed, 0, "totalValueUsed should be 0");
+ }
+
+ function test_validateExplicitCall_invalidChainId(
+ uint64 chainId,
+ uint256 invalidChainId,
+ address target,
+ bytes4 selector,
+ bytes memory callData
+ ) public supportChainId(chainId) {
+ invalidChainId = bound(invalidChainId, 1, type(uint256).max);
+ vm.assume(invalidChainId != chainId);
+ vm.assume(target != address(harness));
+ // Build a payload with one call.
+ Payload.Decoded memory payload = _buildPayload(1);
+ // Prepend the selector to the call data.
+ callData = abi.encodePacked(selector, callData);
+ payload.calls[0] = Payload.Call({
+ to: target,
+ value: 0,
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create SessionPermissions with one Permission.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: invalidChainId,
+ valueLimit: 0, // no native token usage for this test
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ // Allow calls to the target if the selector matches..
+ perms.permissions[0] = Permission({ target: target, rules: new ParameterRule[](1) });
+ perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(selector),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ // Prepare initial session usage limits.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ // Convert our single SessionPermissions into an array.
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ // Call the internal explicit call validator.
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidChainId.selector, invalidChainId));
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_InvalidSessionSigner(
+ address invalidSigner,
+ uint64 chainId
+ ) public supportChainId(chainId) {
+ vm.assume(invalidSigner != sessionWallet.addr);
+ // Build a payload with one call.
+ Payload.Decoded memory payload = _buildPayload(1);
+ bytes memory callData = hex"deadbeef";
+ payload.calls[0] = Payload.Call({
+ to: address(0x1234),
+ value: 0,
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create SessionPermissions with a signer that does NOT match the session signer.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: invalidSigner, // different signer
+ chainId: chainId,
+ valueLimit: 100,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ perms.permissions[0] = Permission({ target: address(0x1234), rules: new ParameterRule[](0) });
+
+ // Create session usage limits.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ // Expect revert with the correct error selector
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidSessionSigner.selector, sessionWallet.addr));
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_SessionExpired(
+ uint64 chainId,
+ uint64 currentTimestamp,
+ uint64 expiredTimestamp
+ ) public supportChainId(chainId) {
+ currentTimestamp = uint64(bound(currentTimestamp, 2, type(uint256).max));
+ expiredTimestamp = uint64(bound(expiredTimestamp, 1, currentTimestamp - 1));
+ vm.warp(currentTimestamp);
+
+ Payload.Decoded memory payload = _buildPayload(1);
+ bytes memory callData = hex"12345678";
+ payload.calls[0] = Payload.Call({
+ to: address(0x1234),
+ value: 0,
+ data: abi.encodePacked(bytes4(0x12345678), callData),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create SessionPermissions with a deadline in the past.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: 100,
+ deadline: expiredTimestamp, // expired
+ permissions: new Permission[](1)
+ });
+ perms.permissions[0] = Permission({ target: address(0x1234), rules: new ParameterRule[](1) });
+ perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(bytes4(0x12345678)),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ // Expect revert due to session expiration with the correct deadline
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.SessionExpired.selector, expiredTimestamp));
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_DelegateCall(
+ uint64 chainId
+ ) public supportChainId(chainId) {
+ Payload.Decoded memory payload = _buildPayload(1);
+ bytes memory callData = hex"12345678";
+ // Set delegateCall to true which is not allowed.
+ payload.calls[0] = Payload.Call({
+ to: address(0x1234),
+ value: 0,
+ data: abi.encodePacked(bytes4(0x12345678), callData),
+ gasLimit: 0,
+ delegateCall: true,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create valid SessionPermissions (won't reach permission check).
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: 100,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ perms.permissions[0] = Permission({ target: address(0x1234), rules: new ParameterRule[](1) });
+ perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(bytes4(0x12345678)),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ vm.expectRevert(SessionErrors.InvalidDelegateCall.selector);
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_InvalidSelfCall_Value(
+ uint64 chainId
+ ) public supportChainId(chainId) {
+ // Self-call with nonzero value should revert.
+ bytes memory callData = abi.encodeWithSelector(harness.incrementUsageLimit.selector, new UsageLimit[](0));
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(harness), // self-call
+ value: 1, // nonzero value
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Need valid session permissions for the test to reach self-call validation
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr, // Match the session signer
+ chainId: chainId,
+ valueLimit: 100,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ perms.permissions[0] = Permission({ target: address(harness), rules: new ParameterRule[](0) });
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_MissingPermission(
+ uint64 chainId
+ ) public supportChainId(chainId) {
+ // Build a valid payload call.
+ bytes memory callData = hex"12345678";
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0x1234),
+ value: 0,
+ data: abi.encodePacked(bytes4(0x12345678), callData),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create SessionPermissions with an empty permissions array.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: 100,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](0)
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ vm.expectRevert(SessionErrors.MissingPermission.selector);
+ // permissionIdx is 0, but there are no permissions.
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_ValueLimitExceeded(
+ uint64 chainId
+ ) public supportChainId(chainId) {
+ // Build a payload call with a nonzero value.
+ bytes memory callData = hex"12345678";
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0] = Payload.Call({
+ to: address(0x1234),
+ value: 20, // call value that will exceed the valueLimit
+ data: abi.encodePacked(bytes4(0x12345678), callData),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Set valueLimit lower than the call value.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: 10, // limit too low
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ perms.permissions[0] = Permission({ target: address(0x1234), rules: new ParameterRule[](1) });
+ perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(bytes4(0x12345678)),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateExplicitCall_InvalidPermission(
+ uint64 chainId
+ ) public supportChainId(chainId) {
+ Payload.Decoded memory payload = _buildPayload(1);
+ // Use call data that does not match the expected selector.
+ bytes memory callData = hex"deadbeef";
+ payload.calls[0] = Payload.Call({
+ to: address(0xDEAD),
+ value: 0,
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Create SessionPermissions expecting selector 0x12345678.
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ perms.permissions[0] = Permission({ target: payload.calls[0].to, rules: new ParameterRule[](1) });
+ perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(bytes4(0x12345678)),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+
+ // Expect a revert with the InvalidPermission error.
+ vm.expectRevert(SessionErrors.InvalidPermission.selector);
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ }
+
+ function test_validateLimitUsageIncrement_rule(
+ UsageLimit memory limit
+ ) public {
+ limit.usageAmount = bound(limit.usageAmount, 1, type(uint256).max);
+
+ // Prepare a call that is intended to be the increment call.
+ Payload.Call memory incCall = Payload.Call({
+ to: address(harness), // must equal the harness address (the contract itself)
+ value: 0,
+ data: "", // will be filled with expected encoding
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Prepare session usage limits with a nonzero totalValueUsed.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](1);
+ usage.limits[0] = limit;
+
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+
+ // Construct the expected usage increment.
+ UsageLimit[] memory limitsArr = new UsageLimit[](1);
+ limitsArr[0] = limit;
+
+ // Encode the expected increment call data.
+ bytes memory expectedData = abi.encodeWithSelector(harness.incrementUsageLimit.selector, limitsArr);
+ incCall.data = expectedData;
+
+ // This call should pass without revert.
+ vm.prank(wallet);
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_validateLimitUsageIncrement_value(
+ uint256 value
+ ) public view {
+ value = bound(value, 1, type(uint256).max);
+
+ // Prepare a call that is intended to be the increment call.
+ Payload.Call memory incCall = Payload.Call({
+ to: address(harness), // must equal the harness address (the contract itself)
+ value: 0,
+ data: "", // will be filled with expected encoding
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Prepare session usage limits with a nonzero totalValueUsed.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0); // no extra limits for simplicity
+ usage.totalValueUsed = value;
+
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+
+ // Construct the expected usage increment.
+ UsageLimit memory expectedLimit =
+ UsageLimit({ usageHash: keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS)), usageAmount: value });
+ UsageLimit[] memory limitsArr = new UsageLimit[](1);
+ limitsArr[0] = expectedLimit;
+
+ // Encode the expected increment call data.
+ bytes memory expectedData = abi.encodeWithSelector(harness.incrementUsageLimit.selector, limitsArr);
+ incCall.data = expectedData;
+
+ // This call should pass without revert.
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_validateLimitUsageIncrement_RuleAndValue(UsageLimit memory limit, uint256 value) public view {
+ limit.usageAmount = bound(limit.usageAmount, 1, type(uint256).max);
+ value = bound(value, 1, type(uint256).max);
+
+ // Prepare a call that is intended to be the increment call.
+ Payload.Call memory incCall = Payload.Call({
+ to: address(harness),
+ value: 0,
+ data: "", // will be filled with expected encoding
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Prepare session usage limits with a nonzero totalValueUsed.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](1);
+ usage.limits[0] = limit;
+ usage.totalValueUsed = value;
+
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+ // Construct the expected usage increment.
+ UsageLimit[] memory limitsArr = new UsageLimit[](2);
+ limitsArr[0] = limit;
+ limitsArr[1] =
+ UsageLimit({ usageHash: keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS)), usageAmount: value });
+
+ // Encode the expected increment call data.
+ bytes memory expectedData = abi.encodeWithSelector(harness.incrementUsageLimit.selector, limitsArr);
+ incCall.data = expectedData;
+
+ // This call should pass without revert.
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_validateLimitUsageIncrement_InvalidBehaviorOnError() public {
+ // Prepare a call with correct target but incorrect behaviorOnError.
+ Payload.Call memory incCall = Payload.Call({
+ to: address(harness),
+ value: 0,
+ data: "invalid", // data is not checked because behaviorOnError is wrong
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: 0 // not the expected Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 100;
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+
+ vm.expectRevert(SessionErrors.InvalidLimitUsageIncrement.selector);
+ vm.prank(wallet);
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_validateLimitUsageIncrement_OnlyFallbackAllowed() public {
+ // Prepare a call with correct target and behaviorOnError but onlyFallback = true
+ // This should revert because increment calls cannot be skippable
+ Payload.Call memory incCall = Payload.Call({
+ to: address(harness),
+ value: 0,
+ data: "invalid", // data is not checked because onlyFallback is wrong
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: true, // This should cause the increment call to be skipped
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 100;
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+
+ // This should revert because increment calls cannot have onlyFallback = true
+ vm.expectRevert(SessionErrors.InvalidLimitUsageIncrement.selector);
+ vm.prank(wallet);
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_validateLimitUsageIncrement_InvalidCallData() public {
+ // Prepare session usage limits with nonzero totalValueUsed.
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 100;
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+
+ // Create a call with the correct target and behaviorOnError but invalid call data.
+ Payload.Call memory incCall = Payload.Call({
+ to: address(harness),
+ value: 0,
+ data: hex"deadbeef", // incorrect encoding
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ vm.expectRevert(SessionErrors.InvalidLimitUsageIncrement.selector);
+ vm.prank(wallet);
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_validateLimitUsageIncrement_InvalidCall() public {
+ // Prepare a call with an incorrect target.
+ Payload.Call memory incCall = Payload.Call({
+ to: address(0xDEAD), // wrong target
+ value: 0,
+ data: "invalid",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 50;
+
+ SessionUsageLimits[] memory usageArr = new SessionUsageLimits[](1);
+ usageArr[0] = usage;
+
+ vm.expectRevert(SessionErrors.InvalidLimitUsageIncrement.selector);
+ vm.prank(wallet);
+ harness.validateLimitUsageIncrement(incCall, usageArr);
+ }
+
+ function test_incrementUsageLimit(
+ UsageLimit[] memory limits
+ ) public {
+ vm.assume(limits.length > 0);
+ // Limit to 5
+ if (limits.length > 5) {
+ assembly {
+ mstore(limits, 5)
+ }
+ }
+
+ // Ensure not duplicates
+ for (uint256 i = 0; i < limits.length; i++) {
+ for (uint256 j = i + 1; j < limits.length; j++) {
+ vm.assume(limits[i].usageHash != limits[j].usageHash);
+ }
+ }
+
+ // Increment the usage limit
+ vm.prank(wallet);
+ harness.incrementUsageLimit(limits);
+
+ // Check totals
+ for (uint256 i = 0; i < limits.length; i++) {
+ assertEq(harness.getLimitUsage(wallet, limits[i].usageHash), limits[i].usageAmount);
+ }
+ }
+
+ function test_incrementUsageLimit_twice(
+ UsageLimit[] memory limits
+ ) public {
+ // Limit to 5
+ if (limits.length > 5) {
+ assembly {
+ mstore(limits, 5)
+ }
+ }
+ // First increment
+ test_incrementUsageLimit(limits);
+ // Bound amount to be larger than the first increment
+ for (uint256 i = 0; i < limits.length; i++) {
+ limits[i].usageAmount = bound(limits[i].usageAmount, limits[i].usageAmount, type(uint256).max);
+ }
+ // Second increment (without checks or tests)
+ vm.prank(wallet);
+ harness.incrementUsageLimit(limits);
+
+ // Check totals
+ for (uint256 i = 0; i < limits.length; i++) {
+ assertEq(harness.getLimitUsage(wallet, limits[i].usageHash), limits[i].usageAmount);
+ }
+ }
+
+ function test_incrementUsageLimit_decrement(
+ UsageLimit memory limit
+ ) public {
+ vm.assume(limit.usageAmount > 0);
+ UsageLimit[] memory limits = new UsageLimit[](2);
+ limits[0] = limit;
+ limits[1] = UsageLimit({ usageHash: limit.usageHash, usageAmount: limit.usageAmount - 1 });
+
+ vm.expectRevert(SessionErrors.InvalidLimitUsageIncrement.selector);
+ vm.prank(wallet);
+ harness.incrementUsageLimit(limits);
+ }
+
+ function test_validateExplicitCall_MultipleValues(
+ uint64 chainId,
+ uint256 firstValue,
+ uint256 secondValue,
+ uint256 thirdValue,
+ uint256 valueLimit
+ ) public supportChainId(chainId) {
+ // Bound values to reasonable ranges
+ firstValue = bound(firstValue, 1, type(uint256).max / 3);
+ secondValue = bound(secondValue, 1, type(uint256).max / 3);
+ thirdValue = bound(thirdValue, 1, type(uint256).max / 3);
+ valueLimit = bound(valueLimit, firstValue + secondValue, firstValue + secondValue + thirdValue - 1);
+
+ // Build a payload with three calls
+ Payload.Decoded memory payload = _buildPayload(3);
+
+ // First call
+ payload.calls[0] = Payload.Call({
+ to: address(0x1234),
+ value: firstValue,
+ data: abi.encodeWithSelector(bytes4(0x12345678)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Second call
+ payload.calls[1] = Payload.Call({
+ to: address(0x5678),
+ value: secondValue,
+ data: abi.encodeWithSelector(bytes4(0x12345678)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Third call
+ payload.calls[2] = Payload.Call({
+ to: address(0x9ABC),
+ value: thirdValue,
+ data: abi.encodeWithSelector(bytes4(0x12345678)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Set valueLimit to allow first two calls but not the third
+ SessionPermissions memory perms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: valueLimit,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](3)
+ });
+
+ // Add permissions for all three targets
+ for (uint256 i = 0; i < 3; i++) {
+ perms.permissions[i] = Permission({ target: payload.calls[i].to, rules: new ParameterRule[](1) });
+ perms.permissions[i].rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(bytes4(0x12345678)),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+ }
+
+ SessionPermissions[] memory permsArr = _toArray(perms);
+ SessionUsageLimits memory usage;
+ usage.signer = sessionWallet.addr;
+ usage.limits = new UsageLimit[](0);
+ usage.totalValueUsed = 0;
+
+ // First transaction: Validate first call
+ SessionUsageLimits memory newUsage =
+ harness.validateExplicitCall(payload, 0, wallet, sessionWallet.addr, permsArr, 0, usage);
+ assertEq(newUsage.totalValueUsed, firstValue, "First call should add firstValue to total value");
+
+ // Increment usage limit after first call
+ UsageLimit[] memory limits = new UsageLimit[](1);
+ limits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS)),
+ usageAmount: firstValue
+ });
+ vm.prank(wallet);
+ harness.incrementUsageLimit(limits);
+
+ // Second transaction: Validate second call
+ newUsage = harness.validateExplicitCall(payload, 1, wallet, sessionWallet.addr, permsArr, 1, newUsage);
+ assertEq(newUsage.totalValueUsed, firstValue + secondValue, "Second call should add secondValue to total value");
+
+ // Increment usage limit after second call
+ limits[0].usageAmount = firstValue + secondValue;
+ vm.prank(wallet);
+ harness.incrementUsageLimit(limits);
+
+ // Third transaction: Try to make third call which should fail
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ harness.validateExplicitCall(payload, 2, wallet, sessionWallet.addr, permsArr, 2, newUsage);
+ }
+
+}
+
+contract ExplicitSessionManagerHarness is ExplicitSessionManager {
+
+ /// @notice Exposes the internal _validateExplicitCall function.
+ function validateExplicitCall(
+ Payload.Decoded calldata payload,
+ uint256 callIdx,
+ address wallet,
+ address sessionWallet,
+ SessionPermissions[] memory allSessionPermissions,
+ uint8 permissionIdx,
+ SessionUsageLimits memory sessionUsageLimits
+ ) public view returns (SessionUsageLimits memory) {
+ return _validateExplicitCall(
+ payload, callIdx, wallet, sessionWallet, allSessionPermissions, permissionIdx, sessionUsageLimits
+ );
+ }
+
+ /// @notice Exposes the internal _validateLimitUsageIncrement function.
+ function validateLimitUsageIncrement(
+ Payload.Call calldata call,
+ SessionUsageLimits[] memory sessionUsageLimits
+ ) public view {
+ _validateLimitUsageIncrement(call, sessionUsageLimits);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/explicit/PermissionValidator.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/explicit/PermissionValidator.t.sol
new file mode 100644
index 000000000..f7d201964
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/explicit/PermissionValidator.t.sol
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Test } from "forge-std/Test.sol";
+
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { PermissionValidator } from "src/extensions/sessions/explicit/PermissionValidator.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+contract PermissionValidatorHarness is PermissionValidator {
+
+ function incrementUsageLimit(address wallet, UsageLimit[] calldata limits) external {
+ for (uint256 i = 0; i < limits.length; i++) {
+ uint256 current = getLimitUsage(wallet, limits[i].usageHash);
+ setLimitUsage(wallet, limits[i].usageHash, current + limits[i].usageAmount);
+ }
+ }
+
+ function callSetLimitUsage(address wallet, bytes32 usageHash, uint256 usageAmount) public {
+ setLimitUsage(wallet, usageHash, usageAmount);
+ }
+
+}
+
+contract PermissionValidatorTest is Test {
+
+ PermissionValidatorHarness validator;
+ address constant TARGET = address(0xDEAD);
+ bytes4 constant DUMMY_SELECTOR = bytes4(0x12345678);
+ bytes32 constant SELECTOR_MASK = bytes32(bytes4(0xffffffff));
+ address constant TEST_WALLET = address(0xBEEF);
+ address constant TEST_SIGNER = address(0xCAFE);
+
+ function setUp() public {
+ validator = new PermissionValidatorHarness();
+ }
+
+ function test_LimitUsageUpdated(address wallet, bytes32 usageHash, uint256 usageAmount) public {
+ vm.expectEmit(true, true, true, true);
+ emit PermissionValidator.LimitUsageUpdated(wallet, usageHash, usageAmount);
+ validator.callSetLimitUsage(wallet, usageHash, usageAmount);
+ assertEq(validator.getLimitUsage(wallet, usageHash), usageAmount);
+ }
+
+ function test_validatePermission_Equal(
+ bytes4 selector
+ ) public view {
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(selector),
+ offset: 0,
+ mask: SELECTOR_MASK
+ });
+
+ // Create a matching call
+ Payload.Call memory call = Payload.Call({
+ to: TARGET,
+ value: 0,
+ data: abi.encodePacked(selector, bytes28(0)),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ UsageLimit[] memory emptyLimits = new UsageLimit[](0);
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+ assertTrue(success, "Permission validation should succeed with matching selector");
+
+ // Test with non-matching call (flip all bits of selector)
+ bytes4 nonMatchingSelector = ~selector;
+ call.data = abi.encodePacked(nonMatchingSelector, bytes28(0));
+ (success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+ assertFalse(success, "Permission validation should fail with non-matching selector");
+ }
+
+ function test_validatePermission_Cumulative(uint256 value, uint256 limit) public {
+ limit = bound(limit, 0, type(uint256).max - 1);
+ value = bound(value, 0, limit);
+
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: true,
+ operation: ParameterOperation.LESS_THAN_OR_EQUAL,
+ value: bytes32(limit),
+ offset: 4, // Offset the selector
+ mask: bytes32(type(uint256).max)
+ });
+
+ Payload.Call memory call = Payload.Call({
+ to: TARGET,
+ value: 0,
+ data: abi.encodeWithSelector(DUMMY_SELECTOR, value),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Initialize usage limits array with space for one limit
+ UsageLimit[] memory emptyLimits = new UsageLimit[](1);
+ emptyLimits[0].usageHash = bytes32(0);
+ emptyLimits[0].usageAmount = 0;
+
+ (bool success, UsageLimit[] memory newLimits) =
+ validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+ assertTrue(success, "First call should succeed");
+ assertEq(newLimits.length, 1, "Should have one usage limit");
+ assertEq(newLimits[0].usageAmount, value, "Usage amount should be value");
+
+ // Increment the limit
+ validator.incrementUsageLimit(TEST_WALLET, newLimits);
+
+ // Create a second call that would exceed the limit
+ value = bound(value, limit - value + 1, type(uint256).max - value);
+ call.data = abi.encodeWithSelector(DUMMY_SELECTOR, value);
+ (success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, newLimits);
+ assertFalse(success, "Second call should fail as it would exceed limit");
+ }
+
+ function test_validatePermission_GreaterThanOrEqual(uint256 threshold, uint256 testValue) public view {
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.GREATER_THAN_OR_EQUAL,
+ value: bytes32(threshold),
+ offset: 0,
+ mask: bytes32(type(uint256).max)
+ });
+
+ Payload.Call memory call = Payload.Call({
+ to: TARGET,
+ value: 0,
+ data: abi.encode(testValue),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ UsageLimit[] memory emptyLimits = new UsageLimit[](0);
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+
+ if (testValue >= threshold) {
+ assertTrue(success, "Should succeed with value >= threshold");
+ } else {
+ assertFalse(success, "Should fail with value < threshold");
+ }
+ }
+
+ function test_validatePermission_NotEqual(uint256 testValue, uint256 compareValue) public view {
+ vm.assume(testValue != compareValue);
+
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.NOT_EQUAL,
+ value: bytes32(compareValue),
+ offset: 0,
+ mask: bytes32(type(uint256).max)
+ });
+
+ Payload.Call memory call = Payload.Call({
+ to: TARGET,
+ value: 0,
+ data: abi.encode(testValue),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ UsageLimit[] memory emptyLimits = new UsageLimit[](0);
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+
+ assertTrue(success, "Should pass when values are not equal");
+ }
+
+ function test_validatePermission_NotEqual_fail(
+ uint256 testValue
+ ) public view {
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.NOT_EQUAL,
+ value: bytes32(testValue),
+ offset: 0,
+ mask: bytes32(type(uint256).max)
+ });
+
+ Payload.Call memory call = Payload.Call({
+ to: TARGET,
+ value: 0,
+ data: abi.encode(testValue),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ UsageLimit[] memory emptyLimits = new UsageLimit[](0);
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+
+ assertFalse(success, "Should fail when values are equal");
+ }
+
+ function test_validatePermission_WithMaskAndOffset(
+ bytes calldata callData,
+ bytes32 mask,
+ uint256 offset,
+ bytes calldata secondCallData
+ ) public view {
+ vm.assume(callData.length >= 32);
+ offset = bound(offset, 0, callData.length - 32);
+
+ // Extract value from calldata at offset
+ bytes32 value;
+ assembly {
+ value := calldataload(add(callData.offset, offset))
+ }
+
+ bytes32 maskedValue = value & mask;
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: maskedValue,
+ offset: offset,
+ mask: mask
+ });
+
+ Payload.Call memory call = Payload.Call({
+ to: TARGET,
+ value: 0,
+ data: callData,
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ UsageLimit[] memory emptyLimits = new UsageLimit[](0);
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+ assertTrue(success, "Should succeed when masked value matches with offset");
+
+ // Second test
+ bytes32 secondValue;
+ assembly {
+ secondValue := calldataload(add(secondCallData.offset, offset))
+ }
+ bytes32 maskedSecondValue = secondValue & mask;
+ call.data = secondCallData;
+ (success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, emptyLimits);
+ if (maskedValue == maskedSecondValue) {
+ // Expect success when values match
+ assertTrue(success, "Should succeed when masked value matches with offset");
+ } else {
+ // Expect failure when values do not match
+ assertFalse(success, "Should fail when masked value does not match with offset");
+ }
+ }
+
+ function test_validatePermission_WrongTarget(
+ address wrongTarget,
+ Payload.Call calldata call,
+ UsageLimit[] calldata usageLimits
+ ) public view {
+ vm.assume(wrongTarget != call.to);
+ Permission memory permission = Permission({ target: TARGET, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(uint256(uint160(TARGET))),
+ offset: 0,
+ mask: bytes32(type(uint256).max)
+ });
+
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, usageLimits);
+ assertFalse(success, "Should fail when target does not match");
+ }
+
+ /// @notice This test passes however in practice memory accessed outside the calldata should be zeroed out using the mask.
+ /// @notice A permission should not be constructed assuming the overflow bytes use the length of the usage limits array...
+ function test_validatePermission_OverflowCalldata_Zeroed(
+ Payload.Call calldata call,
+ uint256 offset,
+ UsageLimit[] calldata usageLimits
+ ) public view {
+ // Ensure there is some overlap with the call data when available
+ uint256 maxOffset = call.data.length > 0 ? call.data.length - 1 : 0;
+ offset = bound(offset, 0, maxOffset);
+
+ bytes32 value;
+ if (offset < call.data.length) {
+ // Get the value from the call data ensuring no overflow accessed
+ value = bytes32(call.data[offset:call.data.length]);
+ }
+ // Get the remaining bytes from the uhh usageLimits size?
+ // Because that's the order the calldata for validatePermission is encoded in here...
+ // This may overflow differently throughout the call stack...
+ bytes32 usageLimitsBytes = bytes32(usageLimits.length);
+ // Right shift the gas limit bytes to the correct position
+ usageLimitsBytes = usageLimitsBytes >> ((call.data.length - offset) * 8);
+ value = value | usageLimitsBytes;
+
+ Permission memory permission = Permission({ target: call.to, rules: new ParameterRule[](1) });
+ permission.rules[0] = ParameterRule({
+ cumulative: false,
+ operation: ParameterOperation.EQUAL,
+ value: value,
+ offset: offset,
+ mask: bytes32(type(uint256).max) // All bits mapped
+ });
+
+ (bool success,) = validator.validatePermission(permission, call, TEST_WALLET, TEST_SIGNER, usageLimits);
+ assertTrue(success, "Should succeed as overflowed calldata is treated as 0");
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/implicit/ImplicitSessionManager.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/implicit/ImplicitSessionManager.t.sol
new file mode 100644
index 000000000..086cb0959
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/extensions/sessions/implicit/ImplicitSessionManager.t.sol
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Vm } from "forge-std/Test.sol";
+
+import { SessionErrors } from "src/extensions/sessions/SessionErrors.sol";
+import { SessionPermissions } from "src/extensions/sessions/explicit/IExplicitSessionManager.sol";
+import { Attestation, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { ISignalsImplicitMode } from "src/extensions/sessions/implicit/ISignalsImplicitMode.sol";
+import { ImplicitSessionManager } from "src/extensions/sessions/implicit/ImplicitSessionManager.sol";
+import { ISapient, Payload } from "src/modules/interfaces/ISapient.sol";
+
+import { SessionTestBase } from "test/extensions/sessions/SessionTestBase.sol";
+import { Emitter } from "test/mocks/Emitter.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+contract ImplicitSessionManagerTest is SessionTestBase {
+
+ using LibAttestation for Attestation;
+
+ ImplicitSessionManagerHarness public sessionManager;
+ Emitter public emitter;
+ address public wallet;
+ Vm.Wallet public sessionWallet;
+ Vm.Wallet public identityWallet;
+
+ function setUp() public {
+ sessionManager = new ImplicitSessionManagerHarness();
+ emitter = new Emitter();
+ wallet = vm.createWallet("wallet").addr;
+ sessionWallet = vm.createWallet("session");
+ identityWallet = vm.createWallet("identity");
+ }
+
+ /// @dev Helper to create a Payload.Call.
+ function _createCall(
+ address to,
+ bool delegateCall,
+ uint256 value,
+ bytes memory data
+ ) internal pure returns (Payload.Call memory call) {
+ call = Payload.Call({
+ to: to,
+ value: value,
+ data: data,
+ gasLimit: 0,
+ delegateCall: delegateCall,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_IGNORE_ERROR
+ });
+ }
+
+ function test_validImplicitCall(Attestation memory attestation, address[] memory blacklist) public view {
+ // Ensure the blacklist doesn't contain the signer or call target
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ vm.assume(blacklist[i] != sessionWallet.addr);
+ vm.assume(blacklist[i] != address(emitter));
+ }
+
+ attestation.approvedSigner = sessionWallet.addr;
+ Payload.Call memory call =
+ _createCall(address(emitter), false, 0, abi.encodeWithSelector(Emitter.implicitEmit.selector));
+
+ // Validate the call
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, blacklist);
+ }
+
+ function test_validImplicitCall_invalidSessionSigner(
+ Attestation memory attestation
+ ) public {
+ vm.assume(attestation.approvedSigner != sessionWallet.addr);
+ address[] memory blacklist = new address[](0);
+ Payload.Call memory call =
+ _createCall(address(emitter), false, 0, abi.encodeWithSelector(Emitter.implicitEmit.selector));
+
+ // Validate the call
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidSessionSigner.selector, sessionWallet.addr));
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, blacklist);
+ }
+
+ function test_blacklistedSessionSignerNotAllowed(
+ uint256 randomIdx,
+ Attestation memory attestation,
+ address[] memory blacklist
+ ) public {
+ // Blacklist the session signer
+ vm.assume(blacklist.length > 0);
+ // Ensure blacklist doesn't contain the emitter
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ vm.assume(blacklist[i] != address(emitter));
+ }
+ // Blacklist the session signer
+ randomIdx = bound(randomIdx, 0, blacklist.length - 1);
+ blacklist[randomIdx] = sessionWallet.addr;
+ // Sort the blacklist
+ _sortAddressesMemory(blacklist);
+
+ attestation.approvedSigner = sessionWallet.addr;
+ Payload.Call memory call =
+ _createCall(address(emitter), false, 0, abi.encodeWithSelector(Emitter.implicitEmit.selector));
+
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.BlacklistedAddress.selector, sessionWallet.addr));
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, blacklist);
+ }
+
+ /// @notice Test for an unsorted blacklist skipping the binary search.
+ function test_blacklist_unsortedSkipsBinarySearch(
+ address[] memory blacklist
+ ) public view {
+ // Ensure not sorted
+ bool isSorted = true;
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ for (uint256 j = 0; j < blacklist.length - i - 1; j++) {
+ if (blacklist[j] > blacklist[j + 1]) {
+ isSorted = false;
+ break;
+ }
+ }
+ }
+ vm.assume(!isSorted);
+
+ bool missedBlacklist = false;
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ if (sessionManager.isAddressBlacklisted(blacklist[i], blacklist)) {
+ missedBlacklist = true;
+ break;
+ }
+ }
+ // Any unsorted blacklist WILL result in missed detection of a blacklisted address in the list
+ assertEq(missedBlacklist, true);
+
+ // Sorting the blacklist will result in all blacklisted addresses being detected
+ _sortAddressesMemory(blacklist);
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ assertEq(sessionManager.isAddressBlacklisted(blacklist[i], blacklist), true);
+ }
+ }
+
+ /// @notice Test for delegateCall not allowed.
+ function test_delegateCallNotAllowed(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+ Payload.Call memory call =
+ _createCall(address(emitter), true, 0, abi.encodeWithSelector(Emitter.implicitEmit.selector));
+ address[] memory emptyBlacklist = new address[](0);
+
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidDelegateCall.selector));
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, emptyBlacklist);
+ }
+
+ function test_nonZeroValueNotAllowed(Attestation memory attestation, uint256 nonZeroValue) public {
+ vm.assume(nonZeroValue > 0);
+ attestation.approvedSigner = sessionWallet.addr;
+ Payload.Call memory call =
+ _createCall(address(emitter), false, nonZeroValue, abi.encodeWithSelector(Emitter.implicitEmit.selector));
+ address[] memory emptyBlacklist = new address[](0);
+
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidValue.selector));
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, emptyBlacklist);
+ }
+
+ function test_blacklistedAddressNotAllowed(
+ uint256 randomIdx,
+ Attestation memory attestation,
+ address[] memory blacklist
+ ) public {
+ // Force the blacklist to contain the call target.
+ vm.assume(blacklist.length > 0);
+ randomIdx = bound(randomIdx, 0, blacklist.length - 1);
+ blacklist[randomIdx] = address(emitter);
+ // Ensure the signer isn't blacklisted
+ for (uint256 i = 0; i < blacklist.length; i++) {
+ vm.assume(blacklist[i] != sessionWallet.addr);
+ }
+ // Sort the blacklist so that binary search in the contract works correctly.
+ _sortAddressesMemory(blacklist);
+
+ attestation.approvedSigner = sessionWallet.addr;
+ Payload.Call memory call =
+ _createCall(address(emitter), false, 0, abi.encodeWithSelector(Emitter.implicitEmit.selector));
+
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.BlacklistedAddress.selector, address(emitter)));
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, blacklist);
+ }
+
+ function test_invalidImplicitResult(
+ Attestation memory attestation
+ ) public {
+ attestation.approvedSigner = sessionWallet.addr;
+
+ // Explicit emit is not approved
+ Payload.Call memory call =
+ _createCall(address(emitter), false, 0, abi.encodeWithSelector(Emitter.explicitEmit.selector));
+ address[] memory emptyBlacklist = new address[](0);
+
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidImplicitResult.selector));
+ sessionManager.validateImplicitCall(call, wallet, sessionWallet.addr, attestation, emptyBlacklist);
+ }
+
+}
+
+contract ImplicitSessionManagerHarness is ImplicitSessionManager {
+
+ /// @notice Exposes the internal _validateImplicitCall function.
+ function validateImplicitCall(
+ Payload.Call calldata call,
+ address wallet,
+ address sessionSigner,
+ Attestation memory attestation,
+ address[] memory blacklist
+ ) public view {
+ _validateImplicitCall(call, wallet, sessionSigner, attestation, blacklist);
+ }
+
+ /// @notice Exposes the internal _isAddressBlacklisted function.
+ function isAddressBlacklisted(address target, address[] memory blacklist) public pure returns (bool) {
+ return _isAddressBlacklisted(target, blacklist);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/recovery/RecoveryDenialOfService.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/recovery/RecoveryDenialOfService.t.sol
new file mode 100644
index 000000000..4fb36fb85
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/recovery/RecoveryDenialOfService.t.sol
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Test, Vm } from "forge-std/Test.sol";
+
+import { AcceptAll } from "test/mocks/AcceptAll.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+import { AdvTest } from "test/utils/TestUtils.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { Recovery } from "src/extensions/recovery/Recovery.sol";
+
+import { Nonce } from "src/modules/Nonce.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+contract IntegrationRecoveryDenialOfService is AdvTest {
+
+ Factory public factory;
+ Stage1Module public module;
+ Recovery public recovery;
+ Vm.Wallet public eoaWallet;
+ Vm.Wallet public recoveryWallet;
+ AcceptAll public mockTarget;
+
+ function setUp() public virtual {
+ eoaWallet = vm.createWallet("eoa");
+ recoveryWallet = vm.createWallet("recovery");
+ recovery = new Recovery();
+ factory = new Factory();
+ module = new Stage1Module(address(factory), address(0));
+ mockTarget = new AcceptAll();
+ }
+
+ struct Signer {
+ address signer;
+ uint24 requiredDeltaTime;
+ uint64 minTimestamp;
+ }
+
+ function _createWalletWithSigner(
+ Signer memory signer
+ ) internal returns (Stage1Module wallet, string memory walletConfig, bytes memory recoveryConfig) {
+ string memory leaves = string.concat(
+ "signer:",
+ vm.toString(signer.signer),
+ ":",
+ vm.toString(signer.requiredDeltaTime),
+ ":",
+ vm.toString(signer.minTimestamp)
+ );
+ recoveryConfig = PrimitivesRPC.recoveryEncode(vm, leaves);
+ bytes32 recoveryImageHash = PrimitivesRPC.recoveryHashFromLeaves(vm, leaves);
+ string memory ce =
+ string(abi.encodePacked("sapient:", vm.toString(recoveryImageHash), ":", vm.toString(address(recovery)), ":1"));
+ ce = string(abi.encodePacked(ce, " signer:", vm.toString(eoaWallet.addr), ":1"));
+ walletConfig = PrimitivesRPC.newConfig(vm, 1, 0, ce);
+ bytes32 imageHash = PrimitivesRPC.getImageHash(vm, walletConfig);
+ wallet = Stage1Module(payable(factory.deploy(address(module), imageHash)));
+
+ return (wallet, walletConfig, recoveryConfig);
+ }
+
+ function _validRecoverySignature(
+ Stage1Module wallet,
+ Payload.Decoded memory payload
+ ) internal view returns (bytes memory signature) {
+ bytes32 recoveryPayloadHash = recovery.recoveryPayloadHash(address(wallet), payload);
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(recoveryWallet.privateKey, recoveryPayloadHash);
+ bytes32 yParityAndS = bytes32((uint256(v - 27) << 255) | uint256(s));
+ signature = abi.encodePacked(r, yParityAndS);
+ }
+
+ function _validWalletSignature(
+ Payload.Decoded memory payload,
+ string memory walletConfig,
+ bytes memory recoveryConfig
+ ) internal returns (bytes memory signature) {
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(recovery)), ":sapient_compact:", vm.toString(recoveryConfig)));
+ signature = PrimitivesRPC.toEncodedSignature(vm, walletConfig, signatures, !payload.noChainId);
+ }
+
+ function test_Recovery_Reexecution(uint160 space, uint64 minTimestamp, uint24 requiredDeltaTime) public {
+ minTimestamp = uint64(bound(minTimestamp, 1, type(uint64).max - requiredDeltaTime));
+ vm.warp(minTimestamp);
+
+ Signer memory signer =
+ Signer({ signer: recoveryWallet.addr, requiredDeltaTime: requiredDeltaTime, minTimestamp: minTimestamp });
+ (Stage1Module wallet, string memory walletConfig, bytes memory recoveryConfig) = _createWalletWithSigner(signer);
+
+ // Prepare recovery payload
+ Payload.Decoded memory recoveryPayload;
+ recoveryPayload.kind = Payload.KIND_TRANSACTIONS;
+ recoveryPayload.calls = new Payload.Call[](1);
+ recoveryPayload.calls[0].to = address(mockTarget);
+ recoveryPayload.space = space;
+
+ // Queue recovery payload
+ bytes memory recoverySignature = _validRecoverySignature(wallet, recoveryPayload);
+ recovery.queuePayload(address(wallet), signer.signer, recoveryPayload, recoverySignature);
+
+ // Wait the required time
+ vm.warp(minTimestamp + requiredDeltaTime);
+
+ // Execute the payload
+ bytes memory walletSignature = _validWalletSignature(recoveryPayload, walletConfig, recoveryConfig);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, recoveryPayload), walletSignature);
+
+ // Resubmission fails
+ vm.expectRevert(abi.encodeWithSelector(Nonce.BadNonce.selector, recoveryPayload.space, recoveryPayload.nonce, 1));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, recoveryPayload), walletSignature);
+ }
+
+ function test_Recovery_DenialOfService(uint160 space, uint64 minTimestamp, uint24 requiredDeltaTime) public {
+ minTimestamp = uint64(bound(minTimestamp, 1, type(uint64).max - requiredDeltaTime));
+ vm.warp(minTimestamp);
+
+ Signer memory signer =
+ Signer({ signer: recoveryWallet.addr, requiredDeltaTime: requiredDeltaTime, minTimestamp: minTimestamp });
+ (Stage1Module wallet, string memory walletConfig, bytes memory recoveryConfig) = _createWalletWithSigner(signer);
+
+ // Prepare recovery payload
+ Payload.Decoded memory recoveryPayload;
+ recoveryPayload.kind = Payload.KIND_TRANSACTIONS;
+ recoveryPayload.calls = new Payload.Call[](1);
+ recoveryPayload.calls[0].to = address(mockTarget);
+ recoveryPayload.calls[0].data = "0x23456789";
+ recoveryPayload.space = space;
+
+ // Queue recovery payload
+ bytes memory recoverySignature = _validRecoverySignature(wallet, recoveryPayload);
+ recovery.queuePayload(address(wallet), signer.signer, recoveryPayload, recoverySignature);
+
+ // Wait the required time
+ vm.warp(minTimestamp + requiredDeltaTime);
+
+ // Block it by having the EOA submit a payload
+ Payload.Decoded memory eoaPayload;
+ eoaPayload.kind = Payload.KIND_TRANSACTIONS;
+ eoaPayload.calls = new Payload.Call[](1);
+ eoaPayload.calls[0].to = address(mockTarget);
+ eoaPayload.calls[0].data = "0x12345678";
+ eoaPayload.space = space;
+
+ // EOA sign
+ bytes32 payloadHash = Payload.hashFor(eoaPayload, address(wallet));
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(eoaWallet, payloadHash);
+ string memory eoaSignatureStr = string(
+ abi.encodePacked(vm.toString(eoaWallet.addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ );
+ bytes memory eoaSignature =
+ PrimitivesRPC.toEncodedSignature(vm, walletConfig, eoaSignatureStr, !eoaPayload.noChainId);
+
+ // Execute with EOA
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, eoaPayload), eoaSignature);
+
+ // Recovery fails
+ bytes memory walletSignature = _validWalletSignature(recoveryPayload, walletConfig, recoveryConfig);
+ vm.expectRevert(abi.encodeWithSelector(Nonce.BadNonce.selector, recoveryPayload.space, recoveryPayload.nonce, 1));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, recoveryPayload), walletSignature);
+ }
+
+ function test_Recovery_CallableByAnyone(
+ uint160 space,
+ uint64 minTimestamp,
+ uint24 requiredDeltaTime,
+ address queuer,
+ address executor
+ ) public {
+ minTimestamp = uint64(bound(minTimestamp, 1, type(uint64).max - requiredDeltaTime));
+ vm.warp(minTimestamp);
+
+ Signer memory signer =
+ Signer({ signer: recoveryWallet.addr, requiredDeltaTime: requiredDeltaTime, minTimestamp: minTimestamp });
+ (Stage1Module wallet, string memory walletConfig, bytes memory recoveryConfig) = _createWalletWithSigner(signer);
+
+ // Prepare recovery payload
+ Payload.Decoded memory recoveryPayload;
+ recoveryPayload.kind = Payload.KIND_TRANSACTIONS;
+ recoveryPayload.calls = new Payload.Call[](1);
+ recoveryPayload.calls[0].to = address(mockTarget);
+ recoveryPayload.space = space;
+
+ // Queue recovery payload
+ bytes memory recoverySignature = _validRecoverySignature(wallet, recoveryPayload);
+ vm.prank(queuer);
+ recovery.queuePayload(address(wallet), signer.signer, recoveryPayload, recoverySignature);
+
+ // Wait the required time
+ vm.warp(minTimestamp + requiredDeltaTime);
+
+ // Execute the payload
+ bytes memory walletSignature = _validWalletSignature(recoveryPayload, walletConfig, recoveryConfig);
+ vm.prank(executor);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, recoveryPayload), walletSignature);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/ExtendedSessionTestBase.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/ExtendedSessionTestBase.sol
new file mode 100644
index 000000000..dfa823f52
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/ExtendedSessionTestBase.sol
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Vm, console } from "forge-std/Test.sol";
+
+import { SessionTestBase } from "test/extensions/sessions/SessionTestBase.sol";
+
+import { AcceptAll } from "test/mocks/AcceptAll.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { EntryPoint } from "account-abstraction/core/EntryPoint.sol";
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { SessionManager, SessionPermissions, SessionSig } from "src/extensions/sessions/SessionManager.sol";
+import { ParameterOperation, ParameterRule, Permission } from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+/// @notice Session signature abuse tests.
+contract ExtendedSessionTestBase is SessionTestBase {
+
+ Factory public factory;
+ Stage1Module public module;
+ SessionManager public sessionManager;
+ Vm.Wallet public sessionWallet;
+ Vm.Wallet public identityWallet;
+ AcceptAll public mockTarget;
+ EntryPoint public entryPoint;
+
+ function setUp() public virtual {
+ sessionWallet = vm.createWallet("session");
+ identityWallet = vm.createWallet("identity");
+ sessionManager = new SessionManager();
+ factory = new Factory();
+ entryPoint = new EntryPoint();
+ module = new Stage1Module(address(factory), address(entryPoint));
+ }
+
+ function _createDefaultTopology() internal returns (string memory topology) {
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(mockTarget), rules: new ParameterRule[](0) });
+ return _createTopology(sessionPerms);
+ }
+
+ function _createTopology(
+ SessionPermissions memory sessionPerms
+ ) internal returns (string memory topology) {
+ topology = PrimitivesRPC.sessionEmpty(vm, identityWallet.addr);
+ string memory sessionPermsJson = _sessionPermissionsToJSON(sessionPerms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, sessionPermsJson, topology);
+ return topology;
+ }
+
+ function _createWallet(
+ string memory topology
+ ) internal returns (Stage1Module wallet, string memory config, bytes32 imageHash) {
+ bytes32 sessionImageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+
+ string memory ce = string(
+ abi.encodePacked("sapient:", vm.toString(sessionImageHash), ":", vm.toString(address(sessionManager)), ":1")
+ );
+ config = PrimitivesRPC.newConfig(vm, 1, 0, ce);
+ imageHash = PrimitivesRPC.getImageHash(vm, config);
+ wallet = Stage1Module(payable(factory.deploy(address(module), imageHash)));
+
+ return (wallet, config, imageHash);
+ }
+
+ function _validExplicitSignature(
+ Payload.Decoded memory payload,
+ Vm.Wallet memory signer,
+ string memory config,
+ string memory topology,
+ uint8[] memory permissionIdxs
+ ) internal returns (bytes memory signature) {
+ string[] memory callSignatures = new string[](payload.calls.length);
+ for (uint256 i = 0; i < payload.calls.length; i++) {
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload, i);
+ string memory sessionSignature = _signAndEncodeRSV(callHash, signer);
+ callSignatures[i] = _explicitCallSignatureToJSON(permissionIdxs[i], sessionSignature);
+ }
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = signer.addr;
+ address[] memory implicitSigners = new address[](0);
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ signature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, !payload.noChainId);
+ }
+
+ function _createValidAttestation(
+ Vm.Wallet memory signer
+ ) internal view returns (Attestation memory) {
+ Attestation memory attestation;
+ attestation.approvedSigner = signer.addr;
+ attestation.authData.redirectUrl = "https://example.com";
+ attestation.authData.issuedAt = uint64(block.timestamp);
+ return attestation;
+ }
+
+ function _validImplicitSignature(
+ Payload.Decoded memory payload,
+ Vm.Wallet memory signer,
+ string memory config,
+ string memory topology
+ ) internal returns (bytes memory signature) {
+ uint256 callCount = payload.calls.length;
+ string[] memory callSignatures = new string[](callCount);
+ Attestation memory attestation = _createValidAttestation(signer);
+ for (uint256 i; i < callCount; i++) {
+ callSignatures[i] = _createImplicitCallSignature(payload, i, signer, identityWallet, attestation);
+ }
+
+ address[] memory explicitSigners = new address[](0);
+ address[] memory implicitSigners = new address[](1);
+ implicitSigners[0] = signer.addr;
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ signature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, !payload.noChainId);
+ }
+
+ struct FuzzPermission {
+ address target;
+ FuzzParameterRule[] rules;
+ }
+
+ struct FuzzParameterRule {
+ bool cumulative;
+ uint8 operation;
+ bytes32 value;
+ uint256 offset;
+ bytes32 mask;
+ }
+
+ function _fuzzToPermission(
+ FuzzPermission memory fuzzPermission,
+ uint256 maxRules
+ ) internal pure returns (Permission memory permission) {
+ uint256 rulesLength = fuzzPermission.rules.length > maxRules ? maxRules : fuzzPermission.rules.length;
+ permission = Permission({ target: fuzzPermission.target, rules: new ParameterRule[](rulesLength) });
+ for (uint256 i = 0; i < rulesLength; i++) {
+ permission.rules[i] = ParameterRule({
+ cumulative: fuzzPermission.rules[i].cumulative,
+ operation: ParameterOperation(fuzzPermission.rules[i].operation % 4),
+ value: fuzzPermission.rules[i].value,
+ offset: fuzzPermission.rules[i].offset,
+ mask: fuzzPermission.rules[i].mask
+ });
+ }
+ return permission;
+ }
+
+ function _fuzzToPermissions(
+ FuzzPermission[] memory fuzzPermissions,
+ uint256 maxPermissions,
+ uint256 maxRules
+ ) internal pure returns (Permission[] memory permissions) {
+ uint256 permissionsLength = fuzzPermissions.length > maxPermissions ? maxPermissions : fuzzPermissions.length;
+ permissions = new Permission[](permissionsLength);
+ for (uint256 i = 0; i < permissionsLength; i++) {
+ permissions[i] = _fuzzToPermission(fuzzPermissions[i], maxRules);
+ }
+ return permissions;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionDenialOfService.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionDenialOfService.t.sol
new file mode 100644
index 000000000..c497d7ab9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionDenialOfService.t.sol
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ExtendedSessionTestBase } from "./ExtendedSessionTestBase.sol";
+import { Vm, console } from "forge-std/Test.sol";
+
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import {
+ SessionErrors, SessionManager, SessionPermissions, SessionSig
+} from "src/extensions/sessions/SessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Calls } from "src/modules/Calls.sol";
+import { Nonce } from "src/modules/Nonce.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+/// @notice Checks for denial of service attacks on or by sessions.
+contract IntegrationSessionDenialOfServiceTest is ExtendedSessionTestBase {
+
+ using Payload for Payload.Decoded;
+
+ function test_DOS_Wallet_SignerRace(
+ uint160 space
+ ) public {
+ space = uint160(bound(space, 0, sessionManager.MAX_SPACE()));
+
+ // Create wallet with sessions and EOA.
+ Vm.Wallet memory eoa = vm.createWallet("eoa");
+ string memory topology = _createDefaultTopology();
+ bytes32 sessionImageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+ string memory ce = string(
+ abi.encodePacked("sapient:", vm.toString(sessionImageHash), ":", vm.toString(address(sessionManager)), ":1")
+ );
+ ce = string(abi.encodePacked(ce, " signer:", vm.toString(eoa.addr), ":1"));
+ string memory config = PrimitivesRPC.newConfig(vm, 1, 0, ce);
+ bytes32 imageHash = PrimitivesRPC.getImageHash(vm, config);
+ Stage1Module wallet = Stage1Module(payable(factory.deploy(address(module), imageHash)));
+
+ // Build payload for EOA to sign
+ Payload.Decoded memory payload1 = _buildPayload(1);
+ payload1.calls = new Payload.Call[](1);
+ payload1.calls[0].to = address(mockTarget);
+ payload1.calls[0].data = "0x12345678";
+ payload1.noChainId = false;
+ payload1.space = space;
+
+ // Sign it with the EOA
+ bytes32 payloadHash = Payload.hashFor(payload1, address(wallet));
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(eoa, payloadHash);
+ string memory eoaSignatureStr = string(
+ abi.encodePacked(vm.toString(eoa.addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ );
+ bytes memory eoaSignature = PrimitivesRPC.toEncodedSignature(vm, config, eoaSignatureStr, !payload1.noChainId);
+
+ //FIXME Check it is approved without running it
+ // wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload1), eoaSignature);
+
+ // Sign a payload with the same nonce to race execution
+ Payload.Decoded memory payload2 = _buildPayload(1);
+ payload2.calls = new Payload.Call[](1);
+ payload2.calls[0].to = address(mockTarget);
+ payload2.calls[0].data = "0x87654321";
+ payload2.space = payload1.space;
+ payload2.nonce = payload1.nonce;
+
+ string[] memory callSignatures = new string[](1);
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload2, 0);
+ string memory callSignature = _signAndEncodeRSV(callHash, sessionWallet);
+ callSignatures[0] = _explicitCallSignatureToJSON(0, callSignature);
+
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+
+ // Construct signature
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ bytes memory sessionSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, !payload2.noChainId);
+
+ // Execute
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload2), sessionSignature);
+
+ // Check the EOA signature is not valid anymore
+ vm.expectRevert(abi.encodeWithSelector(Nonce.BadNonce.selector, payload1.space, payload1.nonce, payload1.nonce + 1));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload1), eoaSignature);
+ }
+
+ function test_DOS_Wallet_StaticSignatureRace(
+ uint160 space
+ ) public {
+ space = uint160(bound(space, 0, sessionManager.MAX_SPACE()));
+
+ // Create wallet with sessions.
+ string memory topology = _createDefaultTopology();
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Build payload for wallet to approve via static signature
+ Payload.Decoded memory payload1 = _buildPayload(1);
+ payload1.calls = new Payload.Call[](1);
+ payload1.calls[0].to = address(mockTarget);
+ payload1.calls[0].data = "0x12345678";
+ payload1.noChainId = false;
+ payload1.space = space;
+
+ // Approve it
+ vm.prank(address(wallet));
+ wallet.setStaticSignature(payload1.hashFor(address(wallet)), identityWallet.addr, uint96(block.timestamp + 1 days));
+ bytes memory staticSignature = bytes(abi.encodePacked(bytes1(0x80)));
+
+ //FIXME Check it is approved without running it
+ // vm.prank(identityWallet.addr);
+ // wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload1), staticSignature);
+
+ // Sign a payload with the same nonce to race execution
+ Payload.Decoded memory payload2 = _buildPayload(1);
+ payload2.calls = new Payload.Call[](1);
+ payload2.calls[0].to = address(mockTarget);
+ payload2.calls[0].data = "0x87654321";
+ payload2.space = payload1.space;
+ payload2.nonce = payload1.nonce;
+
+ string[] memory callSignatures = new string[](1);
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload2, 0);
+ string memory callSignature = _signAndEncodeRSV(callHash, sessionWallet);
+ callSignatures[0] = _explicitCallSignatureToJSON(0, callSignature);
+
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+
+ // Construct signature
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ bytes memory sessionSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, !payload2.noChainId);
+
+ // Execute
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload2), sessionSignature);
+
+ // Check the static signature is not valid anymore
+ vm.expectRevert(abi.encodeWithSelector(Nonce.BadNonce.selector, payload1.space, payload1.nonce, payload1.nonce + 1));
+ vm.prank(identityWallet.addr);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload1), staticSignature);
+ }
+
+ function test_DOS_Wallet_SpaceBlockedHighRange(
+ uint160 space
+ ) public {
+ space = uint160(bound(space, sessionManager.MAX_SPACE() + 1, type(uint160).max));
+
+ // Create wallet with sessions.
+ string memory topology = _createDefaultTopology();
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Sign a payload with the same nonce to race execution
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls = new Payload.Call[](1);
+ payload.calls[0].to = address(mockTarget);
+ payload.calls[0].data = "0x87654321";
+ payload.space = space;
+
+ string[] memory callSignatures = new string[](1);
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload, 0);
+ string memory callSignature = _signAndEncodeRSV(callHash, sessionWallet);
+ callSignatures[0] = _explicitCallSignatureToJSON(0, callSignature);
+
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+
+ // Construct signature
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ bytes memory sessionSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, !payload.noChainId);
+
+ // Execute blocked
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidSpace.selector, space));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), sessionSignature);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionLimitIncrementTest.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionLimitIncrementTest.t.sol
new file mode 100644
index 000000000..7ddc7f6e1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionLimitIncrementTest.t.sol
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ExtendedSessionTestBase } from "./ExtendedSessionTestBase.sol";
+import { Vm, console } from "forge-std/Test.sol";
+
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import {
+ SessionErrors, SessionManager, SessionPermissions, SessionSig
+} from "src/extensions/sessions/SessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Calls } from "src/modules/Calls.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+/// @notice Session limit increment tests.
+contract IntegrationSessionLimitIncrementTest is ExtendedSessionTestBase {
+
+ function test_SessionLimitIncrement_DoSSigner(
+ string memory signer2Name
+ ) public {
+ Vm.Wallet memory signer2 = vm.createWallet(signer2Name);
+ vm.assume(signer2.addr != sessionWallet.addr);
+
+ // Create a topology with the session signer
+ string memory topology = _createDefaultTopology();
+ // Add session signer 2 to the topology
+ SessionPermissions memory signer2Perms = SessionPermissions({
+ signer: signer2.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ signer2Perms.permissions[0] = Permission({ target: address(mockTarget), rules: new ParameterRule[](1) });
+ signer2Perms.permissions[0].rules[0] = ParameterRule({
+ cumulative: true,
+ operation: ParameterOperation.EQUAL,
+ value: bytes32(uint256(1)),
+ offset: 0,
+ mask: bytes32(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
+ });
+ string memory signer2PermsJson = _sessionPermissionsToJSON(signer2Perms);
+ topology = PrimitivesRPC.sessionExplicitAdd(vm, signer2PermsJson, topology);
+ // Create the wallet
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Create a valid payload
+ UsageLimit[] memory usageLimits = new UsageLimit[](1);
+ usageLimits[0] = UsageLimit({
+ usageHash: keccak256(abi.encode(signer2.addr, signer2Perms.permissions[0], uint256(0))),
+ usageAmount: uint256(1)
+ });
+
+ // Make the increment call with signer1
+ Payload.Decoded memory signer1Payload = _buildPayload(1);
+ signer1Payload.calls[0].to = address(sessionManager);
+ signer1Payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, usageLimits);
+ signer1Payload.calls[0].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+
+ // Sign it
+ bytes memory signer1Signature =
+ _validExplicitSignature(signer1Payload, sessionWallet, config, topology, new uint8[](1));
+
+ // Validate we can't DoS it
+ bytes memory packedSigner1Payload = PrimitivesRPC.toPackedPayload(vm, signer1Payload);
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidLimitUsageIncrement.selector));
+ wallet.execute(packedSigner1Payload, signer1Signature);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionSelfCall.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionSelfCall.t.sol
new file mode 100644
index 000000000..39fc666c8
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionSelfCall.t.sol
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ExtendedSessionTestBase, Vm } from "./ExtendedSessionTestBase.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Stage1Module } from "src/Stage1Module.sol";
+import { SessionErrors, SessionPermissions } from "src/extensions/sessions/SessionManager.sol";
+import { ParameterRule, Permission } from "src/extensions/sessions/explicit/Permission.sol";
+
+import { Payload } from "src/modules/Payload.sol";
+
+/// @notice Tests for sessions self-calling.
+contract IntegrationSessionSelfCall is ExtendedSessionTestBase {
+
+ using Payload for Payload.Decoded;
+
+ function setUp() public override {
+ super.setUp();
+ }
+
+ function test_ExplicitSession_SelfCall(
+ bytes32 initImageHash
+ ) external {
+ // Deploy the wallet with an EOA signer
+ Stage1Module wallet = Stage1Module(payable(factory.deploy(address(module), initImageHash)));
+
+ // Update the topology to include a session with self-call permissions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: 0,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(wallet), rules: new ParameterRule[](0) });
+ string memory topology = _createTopology(sessionPerms);
+ bytes32 sessionImageHash = PrimitivesRPC.sessionImageHash(vm, topology);
+ string memory ce = string(
+ abi.encodePacked("sapient:", vm.toString(sessionImageHash), ":", vm.toString(address(sessionManager)), ":1")
+ );
+ string memory updatedConfig = PrimitivesRPC.newConfig(vm, 1, 0, ce);
+ bytes32 updatedImageHash = PrimitivesRPC.getImageHash(vm, updatedConfig);
+
+ // Update the wallet to use the session image hash
+ vm.prank(address(wallet));
+ wallet.updateImageHash(updatedImageHash);
+
+ // Construct a self call payload
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_TRANSACTIONS;
+ payload.calls = new Payload.Call[](1);
+ payload.calls[0] = Payload.Call({
+ to: address(wallet),
+ value: 0,
+ data: hex"12345678",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ // Sign with the session wallet
+ bytes memory signature = _validExplicitSignature(payload, sessionWallet, updatedConfig, topology, new uint8[](1));
+
+ // Execute the self call payload
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, payload);
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidSelfCall.selector));
+ wallet.execute(packedPayload, signature);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionSignatureAbuse.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionSignatureAbuse.t.sol
new file mode 100644
index 000000000..99bfc876d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionSignatureAbuse.t.sol
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ExtendedSessionTestBase } from "./ExtendedSessionTestBase.sol";
+import { Vm, console } from "forge-std/Test.sol";
+
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import {
+ SessionErrors, SessionManager, SessionPermissions, SessionSig
+} from "src/extensions/sessions/SessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Calls } from "src/modules/Calls.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+/// @notice Session signature abuse tests.
+contract IntegrationSessionSignatureAbuseTest is ExtendedSessionTestBase {
+
+ function test_SessionSigner_ZeroAddress_reverts_InvalidSessionSigner(uint8 v, bytes32 s) public {
+ // Create a topology with the session signer
+ string memory topology = _createDefaultTopology();
+
+ // Create a wallet with the topology
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Build the payload
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0].to = address(mockTarget);
+
+ // Build the signature
+ string[] memory callSignatures = new string[](1);
+ bytes32 payloadHash = SessionSig.hashCallWithReplayProtection(payload, 0);
+ bytes32 r = bytes32(0); // Force the signature to return address(0)
+ assertEq(ecrecover(payloadHash, v, r, s), address(0));
+ callSignatures[0] = _explicitCallSignatureToJSON(
+ 0, string(abi.encodePacked(vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)))
+ );
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+ bytes memory sessionSignatures =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures, explicitSigners, implicitSigners);
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures)));
+ bytes memory encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, false);
+
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, payload);
+
+ // Execute
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.InvalidSessionSigner.selector, address(0)));
+ wallet.execute(packedPayload, encodedSignature);
+ }
+
+ function test_PermissionIndex_OutOfRange_reverts_MissingPermission(
+ FuzzPermission[] memory fuzzPermissions,
+ uint8 permissionIndex
+ ) public {
+ // Create permissions for test
+ Permission[] memory permissions = _fuzzToPermissions(fuzzPermissions, 3, 3);
+
+ permissionIndex = uint8(bound(permissionIndex, permissions.length, 2 ** 7 - 1));
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: block.chainid,
+ valueLimit: 0,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: permissions
+ });
+
+ // Create a topology with the session signer
+ string memory topology = _createTopology(sessionPerms);
+
+ // Create a wallet with the topology
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Build the payload
+ Payload.Decoded memory payload = _buildPayload(1);
+ payload.calls[0].to = address(mockTarget);
+
+ // Build the signature
+ uint8[] memory permissionIdxs = new uint8[](1);
+ permissionIdxs[0] = permissionIndex;
+ bytes memory signature = _validExplicitSignature(payload, sessionWallet, config, topology, permissionIdxs);
+
+ // Execute
+ vm.expectRevert(abi.encodeWithSelector(SessionErrors.MissingPermission.selector, permissionIndex));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+ }
+
+ function test_CrossChain_ReplayProtection_RepeatableCall() public {
+ // Create default wallet
+ string memory topology = _createDefaultTopology();
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Build cross chain supported payload
+ Payload.Decoded memory payload1 = _buildPayload(1);
+ payload1.noChainId = true;
+ payload1.calls[0].to = address(mockTarget);
+
+ // Sign
+ string[] memory callSignatures1 = new string[](1);
+ bytes32 callHash = SessionSig.hashCallWithReplayProtection(payload1, 0);
+ string memory sessionSignature = _signAndEncodeRSV(callHash, sessionWallet);
+ callSignatures1[0] = _explicitCallSignatureToJSON(0, sessionSignature);
+
+ address[] memory explicitSigners = new address[](1);
+ explicitSigners[0] = sessionWallet.addr;
+ address[] memory implicitSigners = new address[](0);
+
+ // Assume the signature is submitted on chain 1. Attacker reads signature and crafts replay attack, duplicating call for chain 2.
+ Payload.Decoded memory payload2 = _buildPayload(2);
+ payload2.noChainId = true;
+ payload2.calls[0] = payload1.calls[0];
+ payload2.calls[1] = payload1.calls[0];
+
+ // Sign
+ string[] memory callSignatures2 = new string[](2);
+ callSignatures2[0] = callSignatures1[0];
+ callSignatures2[1] = callSignatures1[0];
+
+ // Construct signature
+ bytes memory sessionSignatures2 =
+ PrimitivesRPC.sessionEncodeCallSignatures(vm, topology, callSignatures2, explicitSigners, implicitSigners);
+ string memory signatures2 =
+ string(abi.encodePacked(vm.toString(address(sessionManager)), ":sapient:", vm.toString(sessionSignatures2)));
+ bytes memory signature2 = PrimitivesRPC.toEncodedSignature(vm, config, signatures2, !payload2.noChainId);
+
+ // Execute
+ try wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload2), signature2) {
+ revert("Execution should fail");
+ } catch (bytes memory reason) {
+ // We don't validate the address in the error
+ bytes4 errorSelector = bytes4(reason);
+ assertEq(errorSelector, SessionErrors.InvalidSessionSigner.selector);
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionUsingERC4337.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionUsingERC4337.t.sol
new file mode 100644
index 000000000..f6d8ec6d3
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionUsingERC4337.t.sol
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ExtendedSessionTestBase } from "./ExtendedSessionTestBase.sol";
+
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { IEntryPoint } from "account-abstraction/core/EntryPoint.sol";
+import { PackedUserOperation } from "account-abstraction/core/UserOperationLib.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { SessionErrors } from "src/extensions/sessions/SessionManager.sol";
+import { ERC4337v07 } from "src/modules/ERC4337v07.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+/// @notice Tests for sessions using ERC4337.
+contract IntegrationSessionUsing4337 is ExtendedSessionTestBase {
+
+ using Payload for Payload.Decoded;
+
+ function setUp() public override {
+ super.setUp();
+ }
+
+ function _prepareUserOp(
+ address sender
+ ) internal returns (PackedUserOperation memory) {
+ // Create a payload to call the mock target contract.
+ Payload.Decoded memory decodedPayload;
+ decodedPayload.kind = Payload.KIND_TRANSACTIONS;
+ decodedPayload.calls = new Payload.Call[](1);
+ decodedPayload.calls[0] = Payload.Call({
+ to: address(mockTarget),
+ value: 0,
+ data: hex"12345678",
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, decodedPayload);
+
+ // Gas stuff
+ uint256 verificationGasLimit = 1_000_000;
+ uint256 callGasLimit = 100_000;
+ uint256 preVerificationGas = 100_000;
+ uint256 maxFeePerGas = block.basefee;
+ uint256 maxPriorityFeePerGas = block.basefee;
+ uint256 totalGasLimit = verificationGasLimit + callGasLimit + preVerificationGas;
+ vm.deal(sender, totalGasLimit * (maxFeePerGas + maxPriorityFeePerGas));
+
+ // Construct the UserOp.
+ PackedUserOperation memory userOp;
+ userOp.callData = abi.encodeWithSelector(ERC4337v07.executeUserOp.selector, packedPayload);
+ userOp.sender = sender;
+ userOp.nonce = 0;
+ userOp.initCode = "";
+ userOp.accountGasLimits = bytes32(abi.encodePacked(uint128(verificationGasLimit), uint128(callGasLimit)));
+ userOp.preVerificationGas = preVerificationGas;
+ userOp.gasFees = bytes32(abi.encodePacked(uint128(maxPriorityFeePerGas), uint128(maxFeePerGas)));
+ userOp.paymasterAndData = "";
+
+ return userOp;
+ }
+
+ function test_ExplicitSession_ERC4337_InvalidPayloadKind(
+ address beneficiary
+ ) external {
+ vm.assume(beneficiary != address(0));
+ beneficiary = boundNoPrecompile(beneficiary);
+ vm.assume(beneficiary.code.length == 0);
+
+ // Deploy the wallet
+ string memory topology = _createDefaultTopology();
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Get the userOpHash that the EntryPoint will use by calling its getUserOpHash function
+ PackedUserOperation memory userOp = _prepareUserOp(address(wallet));
+ bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
+
+ // Create a signature for the userOpHash using the session wallet.
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = userOpHash;
+
+ bytes memory signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](1));
+ userOp.signature = signature;
+
+ PackedUserOperation[] memory ops = new PackedUserOperation[](1);
+ ops[0] = userOp;
+
+ // Check execution fails with the expected error.
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IEntryPoint.FailedOpWithRevert.selector,
+ 0,
+ "AA23 reverted",
+ abi.encodePacked(SessionErrors.InvalidPayloadKind.selector)
+ )
+ );
+ entryPoint.handleOps(ops, payable(beneficiary));
+ }
+
+ function test_ImplicitSession_ERC4337_InvalidPayloadKind(
+ address beneficiary
+ ) external {
+ vm.assume(beneficiary != address(0));
+ beneficiary = boundNoPrecompile(beneficiary);
+ vm.assume(beneficiary.code.length == 0);
+
+ // Deploy the wallet
+ string memory topology = _createDefaultTopology();
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+
+ // Get the userOpHash that the EntryPoint will use by calling its getUserOpHash function
+ PackedUserOperation memory userOp = _prepareUserOp(address(wallet));
+ bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
+
+ // Create a signature for the userOpHash using the session wallet.
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = userOpHash;
+
+ bytes memory signature = _validImplicitSignature(payload, sessionWallet, config, topology);
+ userOp.signature = signature;
+
+ PackedUserOperation[] memory ops = new PackedUserOperation[](1);
+ ops[0] = userOp;
+
+ // Check execution fails with the expected error.
+ vm.expectRevert(
+ abi.encodeWithSelector(
+ IEntryPoint.FailedOpWithRevert.selector,
+ 0,
+ "AA23 reverted",
+ abi.encodePacked(SessionErrors.InvalidPayloadKind.selector)
+ )
+ );
+ entryPoint.handleOps(ops, payable(beneficiary));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionValueForwarding.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionValueForwarding.t.sol
new file mode 100644
index 000000000..95b82db5f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/extensions/sessions/SessionValueForwarding.t.sol
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { ExtendedSessionTestBase } from "./ExtendedSessionTestBase.sol";
+import { Vm, console } from "forge-std/Test.sol";
+
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+
+import { Factory } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import {
+ SessionErrors, SessionManager, SessionPermissions, SessionSig
+} from "src/extensions/sessions/SessionManager.sol";
+import {
+ ParameterOperation, ParameterRule, Permission, UsageLimit
+} from "src/extensions/sessions/explicit/Permission.sol";
+import { Attestation } from "src/extensions/sessions/implicit/Attestation.sol";
+import { Calls } from "src/modules/Calls.sol";
+import { Nonce } from "src/modules/Nonce.sol";
+import { Payload } from "src/modules/Payload.sol";
+import { ValueForwarder } from "test/mocks/ValueForwarder.sol";
+
+/// @notice Checks for value forwarding by sessions.
+contract IntegrationSessionValueForwardingTest is ExtendedSessionTestBase {
+
+ using Payload for Payload.Decoded;
+
+ ValueForwarder public valueForwarder;
+
+ function setUp() public override {
+ super.setUp();
+ valueForwarder = new ValueForwarder();
+ }
+
+ function test_ValueForwarding_Explicit_Limited(
+ uint256 chainId,
+ uint160 space,
+ address recipient,
+ uint256 valueSent,
+ uint256 valueCap
+ ) public {
+ vm.assume(recipient.code.length == 0);
+ chainId = bound(chainId, 0, 2 ** 26 - 1);
+ if (chainId != 0) {
+ vm.chainId(chainId);
+ }
+ space = uint160(bound(space, 0, sessionManager.MAX_SPACE()));
+ valueSent = bound(valueSent, 2, 100 ether);
+ valueCap = bound(valueCap, 1, valueSent - 1); // Under value sent
+
+ // Create wallet with sessions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: valueCap,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(valueForwarder), rules: new ParameterRule[](0) });
+ string memory topology = _createTopology(sessionPerms);
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+ vm.assume(address(wallet) != recipient);
+
+ // Give enough ETH for transfer
+ vm.deal(address(wallet), valueSent);
+
+ // Build payload for transfer
+ Payload.Decoded memory payload = _buildPayload(2);
+ payload.noChainId = chainId == 0;
+ payload.space = space;
+ // Increment
+ UsageLimit[] memory limits = new UsageLimit[](1);
+ limits[0].usageHash = keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS));
+ limits[0].usageAmount = valueSent;
+ payload.calls[0].to = address(sessionManager);
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[0].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ // Send value
+ payload.calls[1].to = address(valueForwarder);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+ payload.calls[1].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+
+ // Sign it with the session
+ bytes memory signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](2));
+
+ // Execute should fail due to limit exceeded
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+
+ // Drop the usage below the limit
+ valueSent = bound(valueSent, 1, valueCap);
+ limits[0].usageAmount = valueSent;
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+
+ // Sign and execute successfully
+ signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](2));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+
+ // Check the balance of the recipient
+ assertEq(address(recipient).balance, valueSent);
+
+ // Try to spend above the limit with new payload
+ payload.nonce++;
+ valueSent = bound(valueSent, valueCap - valueSent + 1, 100 ether);
+ limits[0].usageAmount += valueSent;
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+ // Ensure the wallet has enough ETH
+ vm.deal(address(wallet), valueSent);
+
+ // Sign and fail sending
+ signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](2));
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+ }
+
+ function test_ValueForwarding_Explicit_OverMultipleCalls(
+ uint256 chainId,
+ uint160 space,
+ address recipient,
+ uint256 valueSent,
+ uint256 valueCap
+ ) public {
+ vm.assume(recipient.code.length == 0);
+ chainId = bound(chainId, 0, 2 ** 26 - 1);
+ if (chainId != 0) {
+ vm.chainId(chainId);
+ }
+ space = uint160(bound(space, 0, sessionManager.MAX_SPACE()));
+ valueCap = bound(valueCap, 1 ether, 100 ether);
+ // We will send 3 tx in a batch and want this to overflow
+ valueSent = bound(valueSent, valueCap / 2, 100 ether);
+
+ // Create wallet with sessions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: valueCap,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](1)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(valueForwarder), rules: new ParameterRule[](0) });
+ string memory topology = _createTopology(sessionPerms);
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+ vm.assume(address(wallet) != recipient);
+
+ // Give enough ETH for transfer
+ vm.deal(address(wallet), valueCap);
+
+ // Build payload for transfer
+ Payload.Decoded memory payload = _buildPayload(4);
+ payload.noChainId = chainId == 0;
+ payload.space = space;
+ // Increment
+ UsageLimit[] memory limits = new UsageLimit[](1);
+ limits[0].usageHash = keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS));
+ limits[0].usageAmount = valueSent * 3;
+ payload.calls[0].to = address(sessionManager);
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[0].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ // Send value
+ payload.calls[1].to = address(valueForwarder);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+ payload.calls[1].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ payload.calls[2] = payload.calls[1];
+ payload.calls[3] = payload.calls[1];
+
+ // Sign it with the session
+ bytes memory signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](4));
+
+ // Execute should fail due to limit exceeded
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+
+ // Drop the usage below the limit
+ valueSent = bound(valueSent, 1, valueCap / 3);
+ limits[0].usageAmount = valueSent * 3;
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+ payload.calls[2] = payload.calls[1];
+ payload.calls[3] = payload.calls[1];
+
+ // Sign and execute successfully
+ signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](4));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+
+ // Check the balance of the recipient
+ assertEq(address(recipient).balance, valueSent * 3);
+
+ // Try to spend above the limit with new payload
+ payload.nonce++;
+ valueSent = bound(valueSent, ((valueCap - valueSent * 3) / 3) + 1, 100 ether);
+ limits[0].usageAmount += valueSent * 3; // Should be an increment
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+ payload.calls[2] = payload.calls[1];
+ payload.calls[3] = payload.calls[1];
+ // Ensure the wallet has enough ETH
+ vm.deal(address(wallet), valueSent * 3);
+
+ // Sign and fail sending
+ signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](4));
+ vm.expectRevert(SessionErrors.InvalidValue.selector);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+ }
+
+ function test_ValueForwarding_NoRequiredIncrementAfterIncrement(
+ uint256 chainId,
+ uint160 space,
+ address recipient,
+ uint256 valueSent,
+ uint256 valueCap
+ ) public {
+ vm.assume(recipient.code.length == 0);
+ chainId = bound(chainId, 0, 2 ** 26 - 1);
+ if (chainId != 0) {
+ vm.chainId(chainId);
+ }
+ space = uint160(bound(space, 0, sessionManager.MAX_SPACE()));
+ valueCap = bound(valueCap, 1 ether, 100 ether);
+ valueSent = bound(valueSent, 1, valueCap);
+
+ // Create wallet with sessions
+ SessionPermissions memory sessionPerms = SessionPermissions({
+ signer: sessionWallet.addr,
+ chainId: chainId,
+ valueLimit: valueCap,
+ deadline: uint64(block.timestamp + 1 days),
+ permissions: new Permission[](2)
+ });
+ sessionPerms.permissions[0] = Permission({ target: address(valueForwarder), rules: new ParameterRule[](0) });
+ sessionPerms.permissions[1] = Permission({ target: address(mockTarget), rules: new ParameterRule[](0) });
+ string memory topology = _createTopology(sessionPerms);
+ (Stage1Module wallet, string memory config,) = _createWallet(topology);
+ vm.assume(address(wallet) != recipient);
+
+ // Give enough ETH for transfer
+ vm.deal(address(wallet), valueCap);
+
+ // Build payload for transfer
+ Payload.Decoded memory payload = _buildPayload(2);
+ payload.noChainId = chainId == 0;
+ payload.space = space;
+ // Increment
+ UsageLimit[] memory limits = new UsageLimit[](1);
+ limits[0].usageHash = keccak256(abi.encode(sessionWallet.addr, VALUE_TRACKING_ADDRESS));
+ limits[0].usageAmount = valueSent;
+ payload.calls[0].to = address(sessionManager);
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[0].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ // Send value
+ payload.calls[1].to = address(valueForwarder);
+ payload.calls[1].data = abi.encodeWithSelector(valueForwarder.forwardValue.selector, recipient, valueSent);
+ payload.calls[1].value = valueSent;
+ payload.calls[1].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+
+ // Sign it with the session
+ bytes memory signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](2));
+
+ uint256 recipientBalance = address(recipient).balance;
+ // Sign and execute successfully
+ signature = _validExplicitSignature(payload, sessionWallet, config, topology, new uint8[](4));
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+
+ // Check the balance of the recipient
+ assertEq(address(recipient).balance, recipientBalance + valueSent);
+
+ // Try another payload that doesn't use an increment permission
+ payload = _buildPayload(2);
+ payload.noChainId = chainId == 0;
+ payload.space = space;
+ payload.nonce = 1;
+ // Note: It still needs an increment call, even though there is no increment usage...
+ payload.calls[0].to = address(sessionManager);
+ payload.calls[0].data = abi.encodeWithSelector(sessionManager.incrementUsageLimit.selector, limits);
+ payload.calls[0].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+ // Call mock target
+ payload.calls[1].to = address(mockTarget);
+ payload.calls[1].data = "0x12345678";
+
+ // Sign and send success
+ uint8[] memory permsUsed = new uint8[](2);
+ permsUsed[1] = 1; // Uses mockTarget permission
+ signature = _validExplicitSignature(payload, sessionWallet, config, topology, permsUsed);
+ wallet.execute(PrimitivesRPC.toPackedPayload(vm, payload), signature);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/modules/ERC4337v07/ERC4337Entrypoint.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/modules/ERC4337v07/ERC4337Entrypoint.t.sol
new file mode 100644
index 000000000..881a20042
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/integrations/modules/ERC4337v07/ERC4337Entrypoint.t.sol
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Factory, Wallet } from "src/Factory.sol";
+import { Stage1Module } from "src/Stage1Module.sol";
+import { ERC4337v07 } from "src/modules/ERC4337v07.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+import { Emitter } from "test/mocks/Emitter.sol";
+import { PrimitivesRPC } from "test/utils/PrimitivesRPC.sol";
+import { AdvTest, Vm } from "test/utils/TestUtils.sol";
+
+import { EntryPoint } from "account-abstraction/core/EntryPoint.sol";
+import { PackedUserOperation, UserOperationLib } from "account-abstraction/core/UserOperationLib.sol";
+
+contract IntegrationERC4337v07Test is AdvTest {
+
+ Factory public factory;
+ EntryPoint public entryPoint;
+ Stage1Module public stage1Module;
+ address payable public wallet;
+ string public walletConfig;
+ bytes32 public walletImageHash;
+ Vm.Wallet public signer;
+ Emitter public emitter;
+
+ function setUp() public {
+ factory = new Factory();
+ entryPoint = new EntryPoint();
+ stage1Module = new Stage1Module(address(factory), address(entryPoint));
+
+ // Basic wallet setup for most tests.
+ signer = vm.createWallet("signer");
+ walletConfig =
+ PrimitivesRPC.newConfig(vm, 1, 0, string(abi.encodePacked("signer:", vm.toString(signer.addr), ":1")));
+ walletImageHash = PrimitivesRPC.getImageHash(vm, walletConfig);
+
+ // Setup a mock contract to call.
+ emitter = new Emitter();
+ }
+
+ // --- Helper Functions ---
+
+ function hashRealUserOp(
+ PackedUserOperation calldata userOp
+ ) public pure returns (bytes32) {
+ return UserOperationLib.hash(userOp);
+ }
+
+ function predictWalletAddress(
+ bytes32 imageHash
+ ) public view returns (address) {
+ bytes memory code = abi.encodePacked(Wallet.creationCode, uint256(uint160(address(stage1Module))));
+ bytes32 initCodeHash = keccak256(code);
+
+ return address(uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(factory), imageHash, initCodeHash)))));
+ }
+
+ // --- tests ---
+
+ function _prepareUserOp(
+ address sender
+ ) internal returns (PackedUserOperation memory) {
+ // Create a payload to call the emitter contract.
+ Payload.Decoded memory decodedPayload;
+ decodedPayload.kind = Payload.KIND_TRANSACTIONS;
+ decodedPayload.calls = new Payload.Call[](1);
+ decodedPayload.calls[0] = Payload.Call({
+ to: address(emitter),
+ value: 0,
+ data: abi.encodeWithSelector(Emitter.explicitEmit.selector),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, decodedPayload);
+
+ // Gas stuff
+ uint256 verificationGasLimit = 1_000_000;
+ uint256 callGasLimit = 100_000;
+ uint256 preVerificationGas = 100_000;
+ uint256 maxFeePerGas = block.basefee;
+ uint256 maxPriorityFeePerGas = block.basefee;
+ uint256 totalGasLimit = verificationGasLimit + callGasLimit + preVerificationGas;
+ vm.deal(wallet, totalGasLimit * (maxFeePerGas + maxPriorityFeePerGas));
+
+ // Construct the UserOp.
+ PackedUserOperation memory userOp;
+ userOp.callData = abi.encodeWithSelector(ERC4337v07.executeUserOp.selector, packedPayload);
+ userOp.sender = sender;
+ userOp.nonce = 0;
+ userOp.initCode = "";
+ userOp.accountGasLimits = bytes32(abi.encodePacked(uint128(verificationGasLimit), uint128(callGasLimit)));
+ userOp.preVerificationGas = preVerificationGas;
+ userOp.gasFees = bytes32(abi.encodePacked(uint128(maxPriorityFeePerGas), uint128(maxFeePerGas)));
+ userOp.paymasterAndData = "";
+
+ return userOp;
+ }
+
+ function test_Entrypoint_happypath(
+ address beneficiary
+ ) external {
+ vm.assume(beneficiary != address(0));
+ beneficiary = boundNoPrecompile(beneficiary);
+ vm.assume(beneficiary.code.length == 0);
+
+ // Deploy the wallet
+ wallet = payable(factory.deploy(address(stage1Module), walletImageHash));
+
+ // Get the userOpHash that the EntryPoint will use by calling its getUserOpHash function
+ PackedUserOperation memory userOp = _prepareUserOp(wallet);
+ bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
+
+ // Create a signature for the userOpHash using the wallet's signer config.
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = userOpHash;
+ bytes32 payloadDigest = Payload.hashFor(payload, wallet);
+
+ // Create a signature for the userOpHash using the wallet's signer config.
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, payloadDigest);
+ string memory signatures = string(
+ abi.encodePacked(vm.toString(signer.addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ );
+ userOp.signature = PrimitivesRPC.toEncodedSignature(vm, walletConfig, signatures, true);
+
+ PackedUserOperation[] memory ops = new PackedUserOperation[](1);
+ ops[0] = userOp;
+
+ // Call the entrypoint.
+ vm.expectEmit(true, false, false, true, address(emitter));
+ emit Emitter.Explicit(wallet);
+ entryPoint.handleOps(ops, payable(beneficiary));
+ }
+
+ function test_Entrypoint_initcode(
+ address beneficiary
+ ) external {
+ vm.assume(beneficiary != address(0));
+ beneficiary = boundNoPrecompile(beneficiary);
+ vm.assume(beneficiary.code.length == 0);
+
+ address predictedWallet = predictWalletAddress(walletImageHash);
+
+ // Prepare the userOp with initcode.
+ PackedUserOperation memory userOp = _prepareUserOp(predictedWallet);
+ userOp.initCode = abi.encodePacked(
+ address(factory), abi.encodeWithSelector(Factory.deploy.selector, address(stage1Module), walletImageHash)
+ );
+
+ // Get the userOpHash that the EntryPoint will use by calling its getUserOpHash function
+ bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
+
+ // Create a signature for the userOpHash using the wallet's signer config.
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = userOpHash;
+ bytes32 payloadDigest = Payload.hashFor(payload, predictedWallet);
+
+ // Create a signature for the userOpHash using the wallet's signer config.
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(signer, payloadDigest);
+ string memory signatures = string(
+ abi.encodePacked(vm.toString(signer.addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ );
+ userOp.signature = PrimitivesRPC.toEncodedSignature(vm, walletConfig, signatures, true);
+
+ PackedUserOperation[] memory ops = new PackedUserOperation[](1);
+ ops[0] = userOp;
+
+ // Call the entrypoint.
+ vm.expectEmit(true, false, false, true, address(emitter));
+ emit Emitter.Explicit(predictedWallet);
+ entryPoint.handleOps(ops, payable(beneficiary));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/AcceptAll.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/AcceptAll.sol
new file mode 100644
index 000000000..2baa0ba5d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/AcceptAll.sol
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+contract AcceptAll {
+
+ fallback() external payable { }
+
+ receive() external payable { }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/CanReenter.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/CanReenter.sol
new file mode 100644
index 000000000..99e241b23
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/CanReenter.sol
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+contract CanReenter {
+
+ function doAnotherCall(address target, bytes calldata data) external {
+ (bool success,) = target.call(data);
+ require(success, "Call failed");
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/Emitter.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/Emitter.sol
new file mode 100644
index 000000000..84d0726a9
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/Emitter.sol
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Attestation, LibAttestation } from "src/extensions/sessions/implicit/Attestation.sol";
+
+import { ISignalsImplicitMode } from "src/extensions/sessions/implicit/ISignalsImplicitMode.sol";
+import { Payload } from "src/modules/interfaces/ISapient.sol";
+
+contract Emitter is ISignalsImplicitMode {
+
+ using LibAttestation for Attestation;
+
+ event Implicit(address sender);
+ event Explicit(address sender);
+
+ error InvalidCall(string reason);
+
+ function implicitEmit() external {
+ emit Implicit(msg.sender);
+ }
+
+ function explicitEmit() external {
+ emit Explicit(msg.sender);
+ }
+
+ function acceptImplicitRequest(
+ address wallet,
+ Attestation calldata attestation,
+ Payload.Call calldata call
+ ) external pure returns (bytes32) {
+ if (call.data.length != 4 || bytes4(call.data[:4]) != this.implicitEmit.selector) {
+ return bytes32(0);
+ }
+ // WARNING: This contract does not validate the redirect URL.
+ // All implicit requests are accepted from any project.
+ return attestation.generateImplicitRequestMagic(wallet);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/MockERC20.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/MockERC20.sol
new file mode 100644
index 000000000..157976f85
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/MockERC20.sol
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+contract MockERC20 {
+
+ mapping(address => uint256) public balanceOf;
+ mapping(address => mapping(address => uint256)) public allowance;
+
+ uint256 public totalSupply;
+ string public name = "Mock Token";
+ string public symbol = "MOCK";
+ uint8 public decimals = 18;
+
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(address indexed owner, address indexed spender, uint256 value);
+
+ constructor() {
+ totalSupply = 1000000 * 10 ** decimals;
+ balanceOf[msg.sender] = totalSupply;
+ }
+
+ function transfer(address to, uint256 amount) external returns (bool) {
+ require(balanceOf[msg.sender] >= amount, "Insufficient balance");
+ balanceOf[msg.sender] -= amount;
+ balanceOf[to] += amount;
+ emit Transfer(msg.sender, to, amount);
+ return true;
+ }
+
+ function approve(address spender, uint256 amount) external returns (bool) {
+ allowance[msg.sender][spender] = amount;
+ emit Approval(msg.sender, spender, amount);
+ return true;
+ }
+
+ function transferFrom(address from, address to, uint256 amount) external returns (bool) {
+ require(balanceOf[from] >= amount, "Insufficient balance");
+ require(allowance[from][msg.sender] >= amount, "Insufficient allowance");
+ balanceOf[from] -= amount;
+ balanceOf[to] += amount;
+ allowance[from][msg.sender] -= amount;
+ emit Transfer(from, to, amount);
+ return true;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/MockPayableReceiver.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/MockPayableReceiver.sol
new file mode 100644
index 000000000..f4cf5408a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/MockPayableReceiver.sol
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+contract MockPayableReceiver {
+
+ function receiveValue() external payable { }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/ValueForwarder.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/ValueForwarder.sol
new file mode 100644
index 000000000..d00b1930f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/mocks/ValueForwarder.sol
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+/// @title ValueForwarder
+/// @author Michael Standen
+/// @notice Forwarder for value
+contract ValueForwarder {
+
+ function forwardValue(address to, uint256 value) external payable {
+ (bool success,) = to.call{ value: value }("");
+ require(success, "ValueForwarder: Failed to forward value");
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/BaseSig.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/BaseSig.t.sol
new file mode 100644
index 000000000..9cf7ccffd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/BaseSig.t.sol
@@ -0,0 +1,2550 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../src/modules/Payload.sol";
+import { BaseSig } from "../../src/modules/auth/BaseSig.sol";
+
+import { ICheckpointer, Snapshot } from "../../src/modules/interfaces/ICheckpointer.sol";
+import { ISapient, ISapientCompact } from "../../src/modules/interfaces/ISapient.sol";
+import { PrimitivesRPC } from "../utils/PrimitivesRPC.sol";
+import { AdvTest } from "../utils/TestUtils.sol";
+import { Vm } from "forge-std/Test.sol";
+
+contract BaseSigImp {
+
+ function recoverPub(
+ Payload.Decoded memory _payload,
+ bytes calldata _signature,
+ bool _ignoreCheckpointer,
+ address _checkpointer
+ ) external view returns (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) {
+ return BaseSig.recover(_payload, _signature, _ignoreCheckpointer, _checkpointer);
+ }
+
+}
+
+contract BaseSigTest is AdvTest {
+
+ BaseSigImp public baseSigImp;
+
+ function setUp() public {
+ baseSigImp = new BaseSigImp();
+ }
+
+ function test_recover_random_config_unsigned(uint256 _maxDepth, uint256 _seed) external {
+ _maxDepth = bound(_maxDepth, 1, 6);
+
+ Payload.Decoded memory payload;
+ payload.noChainId = true;
+
+ string memory config = PrimitivesRPC.randomConfig(vm, _maxDepth, _seed, 1, "none");
+ bytes memory encodedConfig = PrimitivesRPC.toEncodedConfig(vm, config);
+
+ (, uint256 weight, bytes32 imageHash,, bytes32 opHash) =
+ baseSigImp.recoverPub(payload, encodedConfig, true, address(0));
+
+ assertEq(weight, 0);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(opHash, Payload.hashFor(payload, address(baseSigImp)));
+ }
+
+ function test_recover_random_config_unsigned_skewed_left(
+ uint256 _seed
+ ) external {
+ uint256 _maxDepth = 54;
+
+ Payload.Decoded memory payload;
+ payload.noChainId = true;
+
+ string memory config = PrimitivesRPC.randomConfig(vm, _maxDepth, _seed, 1, "left");
+ bytes memory encodedConfig = PrimitivesRPC.toEncodedConfig(vm, config);
+
+ (, uint256 weight, bytes32 imageHash,, bytes32 opHash) =
+ baseSigImp.recoverPub(payload, encodedConfig, true, address(0));
+
+ assertEq(weight, 0);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(opHash, Payload.hashFor(payload, address(baseSigImp)));
+ }
+
+ function test_recover_random_config_unsigned_skewed_right(
+ uint256 _seed
+ ) external {
+ uint256 _maxDepth = 54;
+
+ Payload.Decoded memory payload;
+ payload.noChainId = true;
+
+ string memory config = PrimitivesRPC.randomConfig(vm, _maxDepth, _seed, 1, "right");
+ bytes memory encodedConfig = PrimitivesRPC.toEncodedConfig(vm, config);
+
+ (, uint256 weight, bytes32 imageHash,, bytes32 opHash) =
+ baseSigImp.recoverPub(payload, encodedConfig, true, address(0));
+
+ assertEq(weight, 0);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(opHash, Payload.hashFor(payload, address(baseSigImp)));
+ }
+
+ struct AddressWeightPair {
+ address addr;
+ uint8 weight;
+ }
+
+ struct test_recover_one_signer_params {
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ uint256 pk;
+ bool useEthSign;
+ }
+
+ function test_recover_one_signer(
+ test_recover_one_signer_params memory params
+ ) external {
+ vm.assume(params.prefix.length + params.suffix.length < 600);
+
+ boundToLegalPayload(params.payload);
+ params.pk = boundPk(params.pk);
+
+ address signer = vm.addr(params.pk);
+
+ // The signer should not be in the prefix or suffix
+ // or we may end up with more weight than expected
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ vm.assume(params.prefix[i].addr != signer);
+ }
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ vm.assume(params.suffix[i].addr != signer);
+ }
+
+ string memory config;
+
+ {
+ string memory ce;
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " "
+ )
+ );
+ }
+
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(signer), ":", vm.toString(params.weight)));
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, " signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight)
+ )
+ );
+ }
+
+ config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ bytes memory encodedSignature;
+ {
+ bytes32 payloadHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ if (params.useEthSign) {
+ payloadHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", payloadHash));
+ }
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.pk, payloadHash);
+
+ string memory signatureType;
+ if (params.useEthSign) {
+ signatureType = ":eth_sign:";
+ } else {
+ signatureType = ":hash:";
+ }
+
+ string memory signatures = string(
+ abi.encodePacked(vm.toString(signer), signatureType, vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ );
+
+ encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, signatures, !params.payload.noChainId);
+ }
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, encodedSignature, true, address(0));
+
+ assertEq(threshold, params.threshold);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(checkpoint, params.checkpoint);
+ assertEq(weight, params.weight);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_recover_one_1271_signer_params {
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ address signer;
+ bytes signature;
+ }
+
+ function test_recover_one_1271_signer(
+ test_recover_one_1271_signer_params memory params
+ ) external {
+ assumeNotPrecompile2(params.signer);
+ vm.assume(params.prefix.length + params.suffix.length < 600);
+
+ // The signer should not be in the prefix or suffix
+ // or we may end up with more weight than expected
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ vm.assume(params.prefix[i].addr != params.signer);
+ }
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ vm.assume(params.suffix[i].addr != params.signer);
+ }
+
+ boundToLegalPayload(params.payload);
+
+ string memory config;
+
+ {
+ string memory ce;
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " "
+ )
+ );
+ }
+
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(params.signer), ":", vm.toString(params.weight)));
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, " signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight)
+ )
+ );
+ }
+
+ config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ bytes memory encodedSignature;
+ {
+ bytes32 payloadHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ vm.mockCall(
+ address(params.signer),
+ abi.encodeWithSignature("isValidSignature(bytes32,bytes)", payloadHash, params.signature),
+ abi.encode(bytes4(0x1626ba7e))
+ );
+
+ vm.expectCall(
+ address(params.signer),
+ abi.encodeWithSignature("isValidSignature(bytes32,bytes)", payloadHash, params.signature)
+ );
+
+ string memory se =
+ string(abi.encodePacked(vm.toString(params.signer), ":erc1271:", vm.toString(params.signature)));
+
+ encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, se, !params.payload.noChainId);
+ }
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, encodedSignature, true, address(0));
+
+ assertEq(threshold, params.threshold);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(checkpoint, params.checkpoint);
+ assertEq(weight, params.weight);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_recover_one_1271_invalid_signature_fail_params {
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ address signer;
+ bytes signature;
+ bytes revertFromSigner;
+ }
+
+ function test_recover_one_1271_invalid_signature_revert_fail(
+ test_recover_one_1271_invalid_signature_fail_params memory params
+ ) external {
+ assumeNotPrecompile2(params.signer);
+ vm.assume(params.prefix.length + params.suffix.length < 600);
+
+ // The signer should not be in the prefix or suffix
+ // or we may end up with more weight than expected
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ vm.assume(params.prefix[i].addr != params.signer);
+ }
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ vm.assume(params.suffix[i].addr != params.signer);
+ }
+
+ boundToLegalPayload(params.payload);
+
+ string memory config;
+
+ {
+ string memory ce;
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " "
+ )
+ );
+ }
+
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(params.signer), ":", vm.toString(params.weight)));
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, " signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight)
+ )
+ );
+ }
+
+ config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ bytes memory encodedSignature;
+ {
+ bytes32 payloadHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ vm.mockCallRevert(
+ address(params.signer),
+ abi.encodeWithSignature("isValidSignature(bytes32,bytes)", payloadHash, params.signature),
+ params.revertFromSigner
+ );
+
+ string memory se =
+ string(abi.encodePacked(vm.toString(params.signer), ":erc1271:", vm.toString(params.signature)));
+
+ encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, se, !params.payload.noChainId);
+ }
+
+ vm.expectRevert(params.revertFromSigner);
+ baseSigImp.recoverPub(params.payload, encodedSignature, true, address(0));
+ }
+
+ struct test_recover_one_1271_invalid_signature_bad_return_fail_params {
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ address signer;
+ bytes signature;
+ bytes4 bad4Bytes;
+ }
+
+ function test_recover_one_1271_invalid_signature_bad_return_fail(
+ test_recover_one_1271_invalid_signature_bad_return_fail_params memory params
+ ) external {
+ assumeNotPrecompile2(params.signer);
+ vm.assume(params.prefix.length + params.suffix.length < 600);
+
+ if (params.bad4Bytes == bytes4(0x1626ba7e)) {
+ params.bad4Bytes = bytes4(0x00000000);
+ }
+
+ // The signer should not be in the prefix or suffix
+ // or we may end up with more weight than expected
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ vm.assume(params.prefix[i].addr != params.signer);
+ }
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ vm.assume(params.suffix[i].addr != params.signer);
+ }
+
+ boundToLegalPayload(params.payload);
+
+ string memory config;
+
+ {
+ string memory ce;
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " "
+ )
+ );
+ }
+
+ ce = string(abi.encodePacked(ce, "signer:", vm.toString(params.signer), ":", vm.toString(params.weight)));
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, " signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight)
+ )
+ );
+ }
+
+ config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ bytes memory encodedSignature;
+ bytes32 payloadHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ {
+ vm.mockCall(
+ address(params.signer),
+ abi.encodeWithSignature("isValidSignature(bytes32,bytes)", payloadHash, params.signature),
+ abi.encode(params.bad4Bytes)
+ );
+
+ string memory se =
+ string(abi.encodePacked(vm.toString(params.signer), ":erc1271:", vm.toString(params.signature)));
+
+ encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, se, !params.payload.noChainId);
+ }
+
+ vm.expectRevert(
+ abi.encodeWithSelector(BaseSig.InvalidERC1271Signature.selector, payloadHash, params.signer, params.signature)
+ );
+ baseSigImp.recoverPub(params.payload, encodedSignature, true, address(0));
+ }
+
+ struct test_recover_one_sapient_signer_params {
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint8 weight;
+ address signer;
+ bytes signature;
+ bytes32 sapientImageHash;
+ bool isCompact;
+ }
+
+ function test_recover_one_sapient_signer(
+ test_recover_one_sapient_signer_params memory params
+ ) external {
+ assumeNotPrecompile2(params.signer);
+ vm.assume(params.prefix.length + params.suffix.length < 600);
+
+ // The signer should not be in the prefix or suffix
+ // or we may end up with more weight than expected
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ vm.assume(params.prefix[i].addr != params.signer);
+ }
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ vm.assume(params.suffix[i].addr != params.signer);
+ }
+
+ boundToLegalPayload(params.payload);
+
+ string memory config;
+
+ {
+ string memory ce;
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " "
+ )
+ );
+ }
+
+ ce = string(
+ abi.encodePacked(
+ ce,
+ "sapient:",
+ vm.toString(params.sapientImageHash),
+ ":",
+ vm.toString(params.signer),
+ ":",
+ vm.toString(params.weight)
+ )
+ );
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, " signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight)
+ )
+ );
+ }
+
+ config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ bytes memory encodedSignature;
+ {
+ string memory st;
+
+ if (params.isCompact) {
+ st = ":sapient_compact:";
+ bytes32 payloadHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ vm.mockCall(
+ address(params.signer),
+ abi.encodeWithSelector(ISapientCompact.recoverSapientSignatureCompact.selector, payloadHash, params.signature),
+ abi.encode(params.sapientImageHash)
+ );
+
+ vm.expectCall(
+ address(params.signer),
+ abi.encodeWithSelector(ISapientCompact.recoverSapientSignatureCompact.selector, payloadHash, params.signature)
+ );
+ } else {
+ st = ":sapient:";
+ vm.mockCall(
+ address(params.signer),
+ abi.encodeWithSelector(ISapient.recoverSapientSignature.selector, params.payload, params.signature),
+ abi.encode(params.sapientImageHash)
+ );
+
+ vm.expectCall(
+ address(params.signer),
+ abi.encodeWithSelector(ISapient.recoverSapientSignature.selector, params.payload, params.signature)
+ );
+ }
+
+ string memory se = string(abi.encodePacked(vm.toString(params.signer), st, vm.toString(params.signature)));
+
+ encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, se, !params.payload.noChainId);
+ }
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, encodedSignature, true, address(0));
+
+ assertEq(threshold, params.threshold);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(checkpoint, params.checkpoint);
+ assertEq(weight, params.weight);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_recover_nested_config_params {
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ AddressWeightPair[] nestedPrefix;
+ AddressWeightPair[] nestedSuffix;
+ Payload.Decoded payload;
+ uint16 threshold;
+ uint56 checkpoint;
+ uint16 internalThreshold;
+ uint8 externalWeight;
+ uint8 weight;
+ uint256 pk;
+ bool useEthSign;
+ }
+
+ function test_recover_nested_config(
+ test_recover_nested_config_params memory params
+ ) external {
+ vm.assume(
+ params.prefix.length + params.suffix.length + params.nestedPrefix.length + params.nestedSuffix.length < 600
+ );
+
+ boundToLegalPayload(params.payload);
+ params.pk = boundPk(params.pk);
+
+ address signer = vm.addr(params.pk);
+
+ // The signer should not be in the prefix or suffix
+ // or we may end up with more weight than expected
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ vm.assume(params.prefix[i].addr != signer);
+ }
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ vm.assume(params.suffix[i].addr != signer);
+ }
+
+ for (uint256 i = 0; i < params.nestedPrefix.length; i++) {
+ vm.assume(params.nestedPrefix[i].addr != signer);
+ }
+ for (uint256 i = 0; i < params.nestedSuffix.length; i++) {
+ vm.assume(params.nestedSuffix[i].addr != signer);
+ }
+
+ string memory config;
+
+ {
+ string memory ce;
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " "
+ )
+ );
+ }
+
+ string memory nestedContent;
+ for (uint256 i = 0; i < params.nestedPrefix.length; i++) {
+ nestedContent = string(
+ abi.encodePacked(
+ nestedContent,
+ "signer:",
+ vm.toString(params.nestedPrefix[i].addr),
+ ":",
+ vm.toString(params.nestedPrefix[i].weight),
+ " "
+ )
+ );
+ }
+
+ nestedContent =
+ string(abi.encodePacked(nestedContent, "signer:", vm.toString(signer), ":", vm.toString(params.weight)));
+
+ for (uint256 i = 0; i < params.nestedSuffix.length; i++) {
+ nestedContent = string(
+ abi.encodePacked(
+ nestedContent,
+ " signer:",
+ vm.toString(params.nestedSuffix[i].addr),
+ ":",
+ vm.toString(params.nestedSuffix[i].weight)
+ )
+ );
+ }
+
+ ce = string(
+ abi.encodePacked(
+ ce,
+ "nested:",
+ vm.toString(params.internalThreshold),
+ ":",
+ vm.toString(params.externalWeight),
+ ":(",
+ nestedContent,
+ ")"
+ )
+ );
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce = string(
+ abi.encodePacked(
+ ce, " signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight)
+ )
+ );
+ }
+
+ config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+ }
+
+ bytes memory encodedSignature;
+ {
+ bytes32 payloadHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ if (params.useEthSign) {
+ payloadHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", payloadHash));
+ }
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.pk, payloadHash);
+
+ string memory signatureType;
+ if (params.useEthSign) {
+ signatureType = ":eth_sign:";
+ } else {
+ signatureType = ":hash:";
+ }
+
+ string memory se = string(
+ abi.encodePacked(vm.toString(signer), signatureType, vm.toString(r), ":", vm.toString(s), ":", vm.toString(v))
+ );
+
+ encodedSignature = PrimitivesRPC.toEncodedSignature(vm, config, se, !params.payload.noChainId);
+ }
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, encodedSignature, true, address(0));
+
+ assertEq(threshold, params.threshold);
+ assertEq(imageHash, PrimitivesRPC.getImageHash(vm, config));
+ assertEq(checkpoint, params.checkpoint);
+ assertEq(weight, params.weight >= params.internalThreshold ? params.externalWeight : 0);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_recover_chained_signature_single_case_vars {
+ address signer1addr;
+ address signer2addr;
+ address signer3addr;
+ uint256 signer1pk;
+ uint256 signer2pk;
+ uint256 signer3pk;
+ string config1;
+ string config2;
+ string config3;
+ bytes32 config1Hash;
+ bytes32 config2Hash;
+ bytes32 config3Hash;
+ Payload.Decoded payloadApprove2;
+ Payload.Decoded payloadApprove3;
+ bytes signatureForFinalPayload;
+ bytes signature1to2;
+ bytes signature2to3;
+ uint8 v2;
+ bytes32 r2;
+ bytes32 s2;
+ uint8 v3;
+ bytes32 r3;
+ bytes32 s3;
+ uint8 fv;
+ bytes32 fr;
+ bytes32 fs;
+ }
+
+ function test_recover_chained_signature_single_case(
+ Payload.Decoded memory _finalPayload
+ ) external {
+ boundToLegalPayload(_finalPayload);
+
+ test_recover_chained_signature_single_case_vars memory vars;
+
+ vars.signer1pk = 1;
+ vars.signer2pk = 2;
+ vars.signer3pk = 3;
+
+ vars.signer1addr = vm.addr(vars.signer1pk);
+ vars.signer2addr = vm.addr(vars.signer2pk);
+ vars.signer3addr = vm.addr(vars.signer3pk);
+
+ vars.config1 =
+ PrimitivesRPC.newConfig(vm, 1, 1, string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1")));
+
+ vars.config2 = PrimitivesRPC.newConfig(
+ vm,
+ 1,
+ 2,
+ string(
+ abi.encodePacked(
+ "signer:", vm.toString(vars.signer2addr), ":3 ", "signer:", vm.toString(vars.signer1addr), ":2"
+ )
+ )
+ );
+
+ vars.config3 = PrimitivesRPC.newConfig(
+ vm,
+ 1,
+ 3,
+ string(
+ abi.encodePacked(
+ "signer:", vm.toString(vars.signer3addr), ":2 ", "signer:", vm.toString(vars.signer2addr), ":2"
+ )
+ )
+ );
+
+ vars.config1Hash = PrimitivesRPC.getImageHash(vm, vars.config1);
+ vars.config2Hash = PrimitivesRPC.getImageHash(vm, vars.config2);
+ vars.config3Hash = PrimitivesRPC.getImageHash(vm, vars.config3);
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove3.kind = Payload.KIND_CONFIG_UPDATE;
+
+ vars.payloadApprove2.imageHash = vars.config2Hash;
+ vars.payloadApprove3.imageHash = vars.config3Hash;
+
+ {
+ (vars.v2, vars.r2, vars.s2) = vm.sign(vars.signer1pk, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ (vars.v3, vars.r3, vars.s3) = vm.sign(vars.signer2pk, Payload.hashFor(vars.payloadApprove3, address(baseSigImp)));
+ (vars.fv, vars.fr, vars.fs) = vm.sign(vars.signer3pk, Payload.hashFor(_finalPayload, address(baseSigImp)));
+
+ // Signature for final payload
+ vars.signatureForFinalPayload = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config3,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer3addr),
+ ":hash:",
+ vm.toString(vars.fr),
+ ":",
+ vm.toString(vars.fs),
+ ":",
+ vm.toString(vars.fv)
+ )
+ ),
+ !_finalPayload.noChainId
+ );
+
+ // Signatures for links, config3 -> config2 -> config1
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config1,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ true
+ );
+ vars.signature2to3 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config2,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r3),
+ ":",
+ vm.toString(vars.s3),
+ ":",
+ vm.toString(vars.v3)
+ )
+ ),
+ true
+ );
+ }
+
+ bytes[] memory signatures = new bytes[](3);
+ signatures[0] = vars.signatureForFinalPayload;
+ signatures[1] = vars.signature2to3;
+ signatures[2] = vars.signature1to2;
+
+ bytes memory chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ // Recover chained signature
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(_finalPayload, chainedSignature, true, address(0));
+
+ assertEq(threshold, 1);
+ assertEq(weight, 1);
+ assertEq(imageHash, vars.config1Hash);
+ assertEq(checkpoint, 1);
+ assertEq(opHash, Payload.hashFor(_finalPayload, address(baseSigImp)));
+ }
+
+ struct test_recover_subdigest_params {
+ Payload.Decoded payload;
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ uint16 threshold;
+ uint56 checkpoint;
+ }
+
+ function test_recover_subdigest(
+ test_recover_subdigest_params memory params
+ ) public {
+ boundToLegalPayload(params.payload);
+
+ bytes32 opHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ string memory ce;
+
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce =
+ string.concat(ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " ");
+ }
+
+ ce = string.concat(ce, "subdigest:", vm.toString(opHash));
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce =
+ string.concat(ce, " ", "signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight));
+ }
+
+ string memory config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+
+ bytes memory encodedSig = PrimitivesRPC.toEncodedSignature(vm, config, "", !params.payload.noChainId);
+ bytes32 expectedImageHash = PrimitivesRPC.getImageHash(vm, config);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 recoveredOpHash) =
+ baseSigImp.recoverPub(params.payload, encodedSig, true, address(0));
+
+ assertEq(threshold, params.threshold);
+ assertEq(checkpoint, params.checkpoint);
+ assertEq(weight, type(uint256).max);
+ assertEq(recoveredOpHash, opHash);
+ assertEq(imageHash, expectedImageHash);
+ }
+
+ struct test_recover_anyAddressSubdigest_params {
+ Payload.Decoded payload;
+ AddressWeightPair[] prefix;
+ AddressWeightPair[] suffix;
+ uint16 threshold;
+ uint56 checkpoint;
+ }
+
+ function test_recover_anyAddressSubdigest(
+ test_recover_anyAddressSubdigest_params memory params
+ ) public {
+ vm.assume(params.payload.calls.length < 5);
+ boundToLegalPayload(params.payload);
+
+ bytes32 expectedAnyAddressDigest = Payload.hashFor(params.payload, address(0));
+ bytes32 opHash = Payload.hashFor(params.payload, address(baseSigImp));
+
+ string memory ce;
+
+ for (uint256 i = 0; i < params.prefix.length; i++) {
+ ce =
+ string.concat(ce, "signer:", vm.toString(params.prefix[i].addr), ":", vm.toString(params.prefix[i].weight), " ");
+ }
+
+ ce = string.concat(ce, "any-address-subdigest:", vm.toString(expectedAnyAddressDigest));
+
+ for (uint256 i = 0; i < params.suffix.length; i++) {
+ ce =
+ string.concat(ce, " ", "signer:", vm.toString(params.suffix[i].addr), ":", vm.toString(params.suffix[i].weight));
+ }
+
+ string memory config = PrimitivesRPC.newConfig(vm, params.threshold, params.checkpoint, ce);
+
+ bytes memory encodedSig = PrimitivesRPC.toEncodedSignature(vm, config, "", !params.payload.noChainId);
+ bytes32 expectedImageHash = PrimitivesRPC.getImageHash(vm, config);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 recoveredOpHash) =
+ baseSigImp.recoverPub(params.payload, encodedSig, true, address(0));
+
+ assertEq(threshold, params.threshold);
+ assertEq(checkpoint, params.checkpoint);
+ assertEq(weight, type(uint256).max);
+ assertEq(recoveredOpHash, opHash);
+ assertEq(imageHash, expectedImageHash);
+ }
+
+ function test_recover_invalid_signature_flag(
+ Payload.Decoded memory _payload,
+ uint8 checkpointSize,
+ uint8 thresholdSize,
+ uint8 invalidFlag
+ ) external {
+ boundToLegalPayload(_payload);
+
+ invalidFlag = uint8(bound(invalidFlag, BaseSig.FLAG_SIGNATURE_SAPIENT_COMPACT + 1, 15));
+ checkpointSize = uint8(bound(checkpointSize, 0, 7));
+ thresholdSize = uint8(bound(thresholdSize, 0, 1));
+
+ uint8 signatureFlag = uint8((checkpointSize << 2) | (thresholdSize << 5));
+ uint256 thresholdLen = thresholdSize + 1;
+
+ bytes memory signature = new bytes(1 + checkpointSize + thresholdLen + 1);
+ signature[0] = bytes1(signatureFlag);
+
+ signature[1 + checkpointSize + thresholdLen] = bytes1((invalidFlag << 4));
+
+ vm.expectRevert(abi.encodeWithSelector(BaseSig.InvalidSignatureFlag.selector, invalidFlag));
+ baseSigImp.recoverPub(_payload, signature, false, address(0));
+ }
+
+ struct test_recover_chained_low_weight_fail_params {
+ Payload.Decoded payload;
+ uint256 threshold;
+ uint256 weight;
+ uint256 signer1pk;
+ uint256 signer2pk;
+ uint256 signer3pk;
+ }
+
+ struct test_recover_chained_low_weight_fail_vars {
+ address signer1addr;
+ address signer2addr;
+ address signer3addr;
+ string config1;
+ string config2;
+ string config3;
+ bytes32 config1Hash;
+ bytes32 config2Hash;
+ bytes32 config3Hash;
+ Payload.Decoded payloadApprove2;
+ Payload.Decoded payloadApprove3;
+ bytes signatureForFinalPayload;
+ bytes signature1to2;
+ bytes signature2to3;
+ uint8 v2;
+ bytes32 r2;
+ bytes32 s2;
+ uint8 v3;
+ bytes32 r3;
+ bytes32 s3;
+ uint8 fv;
+ bytes32 fr;
+ bytes32 fs;
+ }
+
+ function test_recover_chained_low_weight_fail(
+ test_recover_chained_low_weight_fail_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+ params.weight = bound(params.weight, 0, type(uint8).max);
+ params.threshold = bound(params.threshold, params.weight + 1, type(uint16).max);
+
+ test_recover_chained_low_weight_fail_vars memory vars;
+
+ params.signer1pk = boundPk(params.signer1pk);
+ params.signer2pk = boundPk(params.signer2pk);
+ params.signer3pk = boundPk(params.signer3pk);
+
+ vars.signer1addr = vm.addr(params.signer1pk);
+ vars.signer2addr = vm.addr(params.signer2pk);
+ vars.signer3addr = vm.addr(params.signer3pk);
+
+ vars.config1 =
+ PrimitivesRPC.newConfig(vm, 1, 1, string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1")));
+ vars.config2 = PrimitivesRPC.newConfig(
+ vm,
+ uint16(params.threshold),
+ 2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":", vm.toString(params.weight)))
+ );
+ vars.config3 =
+ PrimitivesRPC.newConfig(vm, 1, 3, string(abi.encodePacked("signer:", vm.toString(vars.signer3addr), ":3")));
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove3.kind = Payload.KIND_CONFIG_UPDATE;
+
+ vars.payloadApprove2.imageHash = vars.config2Hash;
+ vars.payloadApprove3.imageHash = vars.config3Hash;
+
+ {
+ (vars.v2, vars.r2, vars.s2) =
+ vm.sign(params.signer1pk, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ (vars.v3, vars.r3, vars.s3) =
+ vm.sign(params.signer2pk, Payload.hashFor(vars.payloadApprove3, address(baseSigImp)));
+ (vars.fv, vars.fr, vars.fs) = vm.sign(params.signer3pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signatureForFinalPayload = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config3,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer3addr),
+ ":hash:",
+ vm.toString(vars.fr),
+ ":",
+ vm.toString(vars.fs),
+ ":",
+ vm.toString(vars.fv)
+ )
+ ),
+ !params.payload.noChainId
+ );
+
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config1,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ true
+ );
+
+ vars.signature2to3 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config2,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r3),
+ ":",
+ vm.toString(vars.s3),
+ ":",
+ vm.toString(vars.v3)
+ )
+ ),
+ true
+ );
+ }
+
+ bytes[] memory signatures = new bytes[](3);
+ signatures[0] = vars.signatureForFinalPayload;
+ signatures[1] = vars.signature2to3;
+ signatures[2] = vars.signature1to2;
+
+ bytes memory chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ vm.expectRevert(
+ abi.encodeWithSelector(BaseSig.LowWeightChainedSignature.selector, signatures[1], params.threshold, params.weight)
+ );
+ baseSigImp.recoverPub(params.payload, chainedSignature, true, address(0));
+ }
+
+ struct test_recover_chained_wrong_checkpoint_order_fail_params {
+ Payload.Decoded payload;
+ uint256 signer1pk;
+ uint256 signer2pk;
+ uint256 signer3pk;
+ uint256 checkpoint1;
+ uint256 checkpoint2;
+ uint256 checkpoint3;
+ }
+
+ struct test_recover_chained_wrong_checkpoint_order_fail_vars {
+ address signer1addr;
+ address signer2addr;
+ address signer3addr;
+ string config1;
+ string config2;
+ string config3;
+ bytes32 config1Hash;
+ bytes32 config2Hash;
+ bytes32 config3Hash;
+ Payload.Decoded payloadApprove2;
+ Payload.Decoded payloadApprove3;
+ bytes signatureForFinalPayload;
+ bytes signature1to2;
+ bytes signature2to3;
+ uint8 v2;
+ bytes32 r2;
+ bytes32 s2;
+ uint8 v3;
+ bytes32 r3;
+ bytes32 s3;
+ uint8 fv;
+ bytes32 fr;
+ bytes32 fs;
+ }
+
+ function test_recover_chained_wrong_checkpoint_order_fail(
+ test_recover_chained_wrong_checkpoint_order_fail_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+
+ params.checkpoint1 = bound(params.checkpoint1, 0, type(uint56).max);
+ params.checkpoint2 = bound(params.checkpoint2, 0, type(uint56).max);
+ params.checkpoint3 = bound(params.checkpoint3, 0, type(uint56).max);
+
+ // Ensure that either checkpoint2 <= checkpoint1 or checkpoint3 <= checkpoint2
+ if (params.checkpoint2 > params.checkpoint1) {
+ params.checkpoint1 = params.checkpoint2;
+ }
+ if (params.checkpoint3 > params.checkpoint2) {
+ params.checkpoint2 = params.checkpoint3;
+ }
+
+ test_recover_chained_wrong_checkpoint_order_fail_vars memory vars;
+
+ params.signer1pk = boundPk(params.signer1pk);
+ params.signer2pk = boundPk(params.signer2pk);
+ params.signer3pk = boundPk(params.signer3pk);
+
+ vars.signer1addr = vm.addr(params.signer1pk);
+ vars.signer2addr = vm.addr(params.signer2pk);
+ vars.signer3addr = vm.addr(params.signer3pk);
+
+ vars.config1 = PrimitivesRPC.newConfig(
+ vm, 1, params.checkpoint1, string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1"))
+ );
+ vars.config2 = PrimitivesRPC.newConfig(
+ vm, 2, params.checkpoint2, string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":2"))
+ );
+ vars.config3 = PrimitivesRPC.newConfig(
+ vm, 1, params.checkpoint3, string(abi.encodePacked("signer:", vm.toString(vars.signer3addr), ":3"))
+ );
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove3.kind = Payload.KIND_CONFIG_UPDATE;
+
+ vars.payloadApprove2.imageHash = vars.config2Hash;
+ vars.payloadApprove3.imageHash = vars.config3Hash;
+
+ {
+ (vars.v2, vars.r2, vars.s2) =
+ vm.sign(params.signer1pk, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ (vars.v3, vars.r3, vars.s3) =
+ vm.sign(params.signer2pk, Payload.hashFor(vars.payloadApprove3, address(baseSigImp)));
+ (vars.fv, vars.fr, vars.fs) = vm.sign(params.signer3pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signatureForFinalPayload = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config3,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer3addr),
+ ":hash:",
+ vm.toString(vars.fr),
+ ":",
+ vm.toString(vars.fs),
+ ":",
+ vm.toString(vars.fv)
+ )
+ ),
+ !params.payload.noChainId
+ );
+
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config1,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ true
+ );
+
+ vars.signature2to3 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config2,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r3),
+ ":",
+ vm.toString(vars.s3),
+ ":",
+ vm.toString(vars.v3)
+ )
+ ),
+ true
+ );
+ }
+
+ bytes[] memory signatures = new bytes[](3);
+ signatures[0] = vars.signatureForFinalPayload;
+ signatures[1] = vars.signature2to3;
+ signatures[2] = vars.signature1to2;
+
+ bytes memory chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ if (params.checkpoint3 > params.checkpoint2) {
+ vm.expectRevert(
+ abi.encodeWithSelector(BaseSig.WrongChainedCheckpointOrder.selector, params.checkpoint1, params.checkpoint2)
+ );
+ } else {
+ vm.expectRevert(
+ abi.encodeWithSelector(BaseSig.WrongChainedCheckpointOrder.selector, params.checkpoint2, params.checkpoint3)
+ );
+ }
+ baseSigImp.recoverPub(params.payload, chainedSignature, true, address(0));
+ }
+
+ // Checkpointer tests
+
+ struct test_checkpointer_current_snapshot_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ uint56 checkpoint;
+ uint256 signer1pk;
+ uint8 threshold;
+ uint8 weight;
+ bytes checkpointerData;
+ }
+
+ struct test_checkpointer_current_snapshot_vars {
+ address signer1addr;
+ string configJson;
+ bytes32 expectedImageHash;
+ bytes signature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_current_snapshot(
+ test_checkpointer_current_snapshot_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ test_checkpointer_current_snapshot_vars memory vars;
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+ vars.signer1addr = vm.addr(params.signer1pk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ vars.configJson = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpoint,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.expectedImageHash = PrimitivesRPC.getImageHash(vm, vars.configJson);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.signer1pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signature = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.configJson,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ vars.snapshot.imageHash = vars.expectedImageHash;
+ vars.snapshot.checkpoint = params.checkpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.signature, false, address(0));
+ assertEq(threshold, params.threshold);
+ assertEq(weight, params.weight);
+ assertEq(imageHash, vars.snapshot.imageHash);
+ assertEq(checkpoint, vars.snapshot.checkpoint);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_migrate_from_no_checkpointer_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ uint256 signer1pk;
+ uint256 signer2pk;
+ uint8 threshold;
+ uint8 weight;
+ bytes checkpointerData;
+ }
+
+ struct test_checkpointer_migrate_from_no_checkpointer_vars {
+ address signer1addr;
+ address signer2addr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_migrate_from_no_checkpointer(
+ test_checkpointer_migrate_from_no_checkpointer_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ test_checkpointer_migrate_from_no_checkpointer_vars memory vars;
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+ params.signer2pk = boundPk(params.signer2pk);
+ vars.signer1addr = vm.addr(params.signer1pk);
+ vars.signer2addr = vm.addr(params.signer2pk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ // Ensure checkpoint2 > checkpoint1 for proper ordering
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 0, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+
+ // Create config1 (old config without checkpointer)
+ vars.config1Json = PrimitivesRPC.newConfig(
+ vm,
+ params.threshold,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ // Create config2 (new config with checkpointer)
+ vars.config2Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":", vm.toString(params.weight)))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ // Create config update payload from config1 to config2
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ // Sign the config update payload with config1 (no checkpointer)
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signer1pk, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false
+ );
+
+ // Sign the main payload with config2 (with checkpointer)
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signer2pk, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ // Mock the checkpointer to return the new config's snapshot
+ vars.snapshot.imageHash = vars.config2ImageHash;
+ vars.snapshot.checkpoint = params.checkpoint2;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ // Create chained signature (reverse order: final signature first, then intermediate)
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, params.threshold);
+ assertEq(weight, params.weight);
+ assertEq(imageHash, vars.config1ImageHash); // Should recover to the first config in the chain
+ assertEq(checkpoint, params.checkpoint1); // Should use checkpoint from the first config
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_migrate_to_no_checkpointer_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ uint256 signer1pk;
+ uint256 signer2pk;
+ uint8 threshold;
+ uint8 weight;
+ bytes checkpointerData;
+ }
+
+ struct test_checkpointer_migrate_to_no_checkpointer_vars {
+ address signer1addr;
+ address signer2addr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_migrate_to_no_checkpointer(
+ test_checkpointer_migrate_to_no_checkpointer_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ test_checkpointer_migrate_to_no_checkpointer_vars memory vars;
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+ params.signer2pk = boundPk(params.signer2pk);
+ vars.signer1addr = vm.addr(params.signer1pk);
+ vars.signer2addr = vm.addr(params.signer2pk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ // Ensure checkpoint2 > checkpoint1 for proper ordering
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 0, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+
+ // Create config1 (old config with checkpointer)
+ vars.config1Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ // Create config2 (new config without checkpointer)
+ vars.config2Json = PrimitivesRPC.newConfig(
+ vm,
+ params.threshold,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":", vm.toString(params.weight)))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ // Create config update payload from config1 to config2
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ // Sign the config update payload with config1 (with checkpointer)
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signer1pk, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false,
+ params.checkpointerData
+ );
+
+ // Sign the main payload with config2 (without checkpointer)
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signer2pk, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignature(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId
+ );
+
+ // Mock the checkpointer to return the old config's snapshot
+ vars.snapshot.imageHash = vars.config1ImageHash;
+ vars.snapshot.checkpoint = params.checkpoint1;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ // Create chained signature (reverse order: final signature first, then intermediate)
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, params.threshold);
+ assertEq(weight, params.weight);
+ assertEq(imageHash, vars.config1ImageHash); // Should recover to the first config in the chain
+ assertEq(checkpoint, params.checkpoint1); // Should use checkpoint from the first config
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_migrate_from_snapshot_to_snapshot_params {
+ Payload.Decoded payload;
+ address checkpointerA;
+ address checkpointerB;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ uint256 signerpk;
+ uint8 threshold;
+ uint8 weight;
+ bytes checkpointerAData;
+ }
+
+ struct test_checkpointer_migrate_from_snapshot_to_snapshot_vars {
+ address signeraddr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ Snapshot snapshotA;
+ }
+
+ function test_checkpointer_migrate_from_snapshot_to_snapshot(
+ test_checkpointer_migrate_from_snapshot_to_snapshot_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ test_checkpointer_migrate_from_snapshot_to_snapshot_vars memory vars;
+ boundToLegalPayload(params.payload);
+
+ params.checkpointerA = boundNoPrecompile(params.checkpointerA);
+ params.checkpointerB = boundNoPrecompile(params.checkpointerB);
+ // Ensure checkpointerA != checkpointerB
+ vm.assume(params.checkpointerA != params.checkpointerB);
+
+ params.signerpk = boundPk(params.signerpk);
+ vars.signeraddr = vm.addr(params.signerpk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ // Ensure checkpoint2 > checkpoint1 for proper ordering
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 0, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+
+ // Create config1 (old config with checkpointer A)
+ vars.config1Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointerA,
+ params.threshold,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signeraddr), ":", vm.toString(params.weight)))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ // Create config2 (new config with checkpointer B)
+ vars.config2Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointerB,
+ params.threshold,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signeraddr), ":", vm.toString(params.weight)))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ // Create config update payload from config1 to config2
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ // Sign the config update payload with config1 (with checkpointer A)
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signerpk, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signeraddr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false,
+ params.checkpointerAData
+ );
+
+ // Sign the main payload with config2 (with checkpointer B)
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signerpk, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signeraddr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId,
+ ""
+ );
+
+ // Mock checkpointer A to return the old config's snapshot
+ vars.snapshotA.imageHash = vars.config1ImageHash;
+ vars.snapshotA.checkpoint = params.checkpoint1;
+
+ // Only checkpointer A is called
+ vm.mockCall(
+ params.checkpointerA, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshotA)
+ );
+
+ // Create chained signature (reverse order: final signature first, then intermediate)
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, params.threshold);
+ assertEq(weight, params.weight);
+ assertEq(imageHash, vars.config1ImageHash); // Should recover to the first config in the chain
+ assertEq(checkpoint, params.checkpoint1); // Should use checkpoint from the first config
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_higher_checkpoint_fail_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ bytes checkpointerData;
+ uint56 checkpointerCheckpoint;
+ uint56 checkpoint;
+ uint256 signer1pk;
+ uint8 threshold;
+ uint8 weight;
+ }
+
+ struct test_checkpointer_higher_checkpoint_fail_vars {
+ address signer1addr;
+ string configJson;
+ bytes32 expectedImageHash;
+ bytes signature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_higher_checkpoint_fail(
+ test_checkpointer_higher_checkpoint_fail_params memory params
+ ) external {
+ boundToLegalPayload(params.payload);
+
+ params.checkpointerCheckpoint = uint56(bound(params.checkpointerCheckpoint, 1, type(uint56).max));
+ params.checkpoint = uint56(bound(params.checkpoint, 0, params.checkpointerCheckpoint - 1));
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ test_checkpointer_higher_checkpoint_fail_vars memory vars;
+
+ vars.configJson = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpointerCheckpoint,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.expectedImageHash = PrimitivesRPC.getImageHash(vm, vars.configJson);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.signer1pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signature = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.configJson,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ vars.snapshot.imageHash = vars.expectedImageHash;
+ vars.snapshot.checkpoint = params.checkpointerCheckpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ vm.expectRevert(abi.encodeWithSelector(BaseSig.UnusedSnapshot.selector, vars.snapshot));
+ baseSigImp.recoverPub(params.payload, vars.signature, false, address(0));
+ }
+
+ struct test_checkpointer_different_image_hash_fail_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ bytes checkpointerData;
+ uint56 checkpoint;
+ uint256 signer1pk;
+ uint8 threshold;
+ uint8 weight;
+ bytes32 differentImageHash;
+ }
+
+ struct test_checkpointer_different_image_hash_fail_vars {
+ address signer1addr;
+ string configJson;
+ bytes32 expectedImageHash;
+ bytes signature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_different_image_hash_fail(
+ test_checkpointer_different_image_hash_fail_params memory params
+ ) external {
+ vm.assume(params.differentImageHash != bytes32(0));
+
+ boundToLegalPayload(params.payload);
+
+ params.checkpoint = uint56(bound(params.checkpoint, 0, type(uint56).max));
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ test_checkpointer_different_image_hash_fail_vars memory vars;
+
+ vars.signer1addr = vm.addr(params.signer1pk);
+ vars.configJson = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpoint,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.expectedImageHash = PrimitivesRPC.getImageHash(vm, vars.configJson);
+
+ // Ensure the different imageHash is actually different from the expected one and not zero
+ vm.assume(params.differentImageHash != vars.expectedImageHash);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.signer1pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signature = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.configJson,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ // Use the provided different imageHash
+ vars.snapshot.imageHash = params.differentImageHash;
+ vars.snapshot.checkpoint = params.checkpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ vm.expectRevert(abi.encodeWithSelector(BaseSig.UnusedSnapshot.selector, vars.snapshot));
+ baseSigImp.recoverPub(params.payload, vars.signature, false, address(0));
+ }
+
+ struct test_checkpointer_disabled_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ uint56 checkpoint;
+ uint56 snapshotCheckpoint;
+ uint256 signer1pk;
+ uint8 threshold;
+ uint8 weight;
+ bytes checkpointerData;
+ }
+
+ struct test_checkpointer_disabled_vars {
+ address signer1addr;
+ string configJson;
+ bytes32 expectedImageHash;
+ bytes signature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_disabled(
+ test_checkpointer_disabled_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ test_checkpointer_disabled_vars memory vars;
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+ vars.signer1addr = vm.addr(params.signer1pk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ vars.configJson = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpoint,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.expectedImageHash = PrimitivesRPC.getImageHash(vm, vars.configJson);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.signer1pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signature = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.configJson,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ // Set imageHash to 0 to indicate checkpointer is disabled
+ vars.snapshot.imageHash = bytes32(0);
+ vars.snapshot.checkpoint = params.snapshotCheckpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.signature, false, address(0));
+ assertEq(threshold, params.threshold);
+ assertEq(weight, params.weight);
+ assertEq(imageHash, vars.expectedImageHash);
+ assertEq(checkpoint, params.checkpoint); // Should use checkpoint from config, not snapshot
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_disabled_old_checkpoint_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ uint56 checkpoint;
+ uint56 snapshotCheckpoint;
+ uint256 signer1pk;
+ uint8 threshold;
+ uint8 weight;
+ bytes checkpointerData;
+ bytes32 ignoredImageHash;
+ uint56 oldCheckpoint;
+ }
+
+ struct test_checkpointer_disabled_old_checkpoint_vars {
+ address signer1addr;
+ string configJson;
+ bytes32 expectedImageHash;
+ bytes signature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_disabled_old_checkpoint(
+ test_checkpointer_disabled_old_checkpoint_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ test_checkpointer_disabled_old_checkpoint_vars memory vars;
+ boundToLegalPayload(params.payload);
+
+ params.checkpoint = uint56(bound(params.checkpoint, 1, type(uint56).max));
+ params.oldCheckpoint = uint56(bound(params.oldCheckpoint, 0, params.checkpoint - 1));
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signer1pk = boundPk(params.signer1pk);
+ vars.signer1addr = vm.addr(params.signer1pk);
+
+ params.weight = uint8(bound(params.weight, params.threshold, type(uint8).max));
+
+ vars.configJson = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ params.threshold,
+ params.checkpoint,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":", vm.toString(params.weight)))
+ );
+ vars.expectedImageHash = PrimitivesRPC.getImageHash(vm, vars.configJson);
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(params.signer1pk, Payload.hashFor(params.payload, address(baseSigImp)));
+
+ vars.signature = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.configJson,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ // Set imageHash to 0 to indicate checkpointer is disabled
+ vars.snapshot.imageHash = params.ignoredImageHash;
+ vars.snapshot.checkpoint = params.oldCheckpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.signature, false, address(0));
+ assertEq(threshold, params.threshold);
+ assertEq(weight, params.weight);
+ assertEq(imageHash, vars.expectedImageHash);
+ assertEq(checkpoint, params.checkpoint); // Should use checkpoint from config, not snapshot
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_past_with_chain_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ bytes checkpointerData;
+ uint256 signerPk1;
+ uint256 signerPk2;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ }
+
+ struct test_checkpointer_past_with_chain_vars {
+ address signer1addr;
+ address signer2addr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ Snapshot snapshot;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ }
+
+ function test_checkpointer_past_with_chain(
+ test_checkpointer_past_with_chain_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signerPk1 = boundPk(params.signerPk1);
+ params.signerPk2 = boundPk(params.signerPk2);
+
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 0, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+
+ test_checkpointer_past_with_chain_vars memory vars;
+
+ vars.signer1addr = vm.addr(params.signerPk1);
+ vars.signer2addr = vm.addr(params.signerPk2);
+
+ vars.config1Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 1,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1"))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ vars.config2Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 2,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":2"))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signerPk1, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false,
+ params.checkpointerData
+ );
+
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signerPk2, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ vars.snapshot.imageHash = vars.config2ImageHash;
+ vars.snapshot.checkpoint = params.checkpoint2;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, 1);
+ assertEq(weight, 1);
+ assertEq(imageHash, vars.config1ImageHash);
+ assertEq(checkpoint, params.checkpoint1);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_disabled_with_chain_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ bytes checkpointerData;
+ uint256 signerPk1;
+ uint256 signerPk2;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ uint56 ignoredSnapshotCheckpoint;
+ }
+
+ struct test_checkpointer_disabled_with_chain_vars {
+ address signer1addr;
+ address signer2addr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_disabled_with_chain(
+ test_checkpointer_disabled_with_chain_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signerPk1 = boundPk(params.signerPk1);
+ params.signerPk2 = boundPk(params.signerPk2);
+
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 0, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+
+ test_checkpointer_disabled_with_chain_vars memory vars;
+
+ vars.signer1addr = vm.addr(params.signerPk1);
+ vars.signer2addr = vm.addr(params.signerPk2);
+
+ vars.config1Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 1,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1"))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ vars.config2Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 2,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":2"))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signerPk1, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false,
+ params.checkpointerData
+ );
+
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signerPk2, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ vars.snapshot.imageHash = bytes32(0);
+ vars.snapshot.checkpoint = params.ignoredSnapshotCheckpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, 1);
+ assertEq(weight, 1);
+ assertEq(imageHash, vars.config1ImageHash);
+ assertEq(checkpoint, params.checkpoint1);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_old_checkpoint_with_chain_params {
+ Payload.Decoded payload;
+ address checkpointer;
+ bytes checkpointerData;
+ uint256 signerPk1;
+ uint256 signerPk2;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ uint56 oldCheckpoint;
+ bytes32 ignoredImageHash;
+ }
+
+ struct test_checkpointer_old_checkpoint_with_chain_vars {
+ address signer1addr;
+ address signer2addr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_old_checkpoint_with_chain(
+ test_checkpointer_old_checkpoint_with_chain_params memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signerPk1 = boundPk(params.signerPk1);
+ params.signerPk2 = boundPk(params.signerPk2);
+
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 1, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+ params.oldCheckpoint = uint56(bound(params.oldCheckpoint, 0, params.checkpoint1 - 1));
+
+ test_checkpointer_old_checkpoint_with_chain_vars memory vars;
+
+ vars.signer1addr = vm.addr(params.signerPk1);
+ vars.signer2addr = vm.addr(params.signerPk2);
+
+ vars.config1Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 1,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1"))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ vars.config2Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 2,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":2"))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signerPk1, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false,
+ params.checkpointerData
+ );
+
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signerPk2, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ vars.snapshot.imageHash = params.ignoredImageHash;
+ vars.snapshot.checkpoint = params.oldCheckpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint, bytes32 opHash) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, 1);
+ assertEq(weight, 1);
+ assertEq(imageHash, vars.config1ImageHash);
+ assertEq(checkpoint, params.checkpoint1);
+ assertEq(opHash, Payload.hashFor(params.payload, address(baseSigImp)));
+ }
+
+ struct test_checkpointer_unused_snapshot_chain_params_fail {
+ Payload.Decoded payload;
+ address checkpointer;
+ bytes checkpointerData;
+ uint256 signerPk1;
+ uint256 signerPk2;
+ uint56 checkpoint1;
+ uint56 checkpoint2;
+ uint56 snapshotCheckpoint;
+ bytes32 snapshotImageHash;
+ }
+
+ struct test_checkpointer_unused_snapshot_chain_vars_fail {
+ address signer1addr;
+ address signer2addr;
+ string config1Json;
+ string config2Json;
+ bytes32 config1ImageHash;
+ bytes32 config2ImageHash;
+ bytes signature1to2;
+ bytes signature2toPayload;
+ bytes32 r1;
+ bytes32 r2;
+ bytes32 s1;
+ bytes32 s2;
+ uint8 v1;
+ uint8 v2;
+ Payload.Decoded payloadApprove2;
+ bytes chainedSignature;
+ Snapshot snapshot;
+ }
+
+ function test_checkpointer_unused_snapshot_chain_fail(
+ test_checkpointer_unused_snapshot_chain_params_fail memory params
+ ) external {
+ vm.assume(params.payload.calls.length < 3);
+ boundToLegalPayload(params.payload);
+
+ params.checkpointer = boundNoPrecompile(params.checkpointer);
+ params.signerPk1 = boundPk(params.signerPk1);
+ params.signerPk2 = boundPk(params.signerPk2);
+
+ params.checkpoint1 = uint56(bound(params.checkpoint1, 0, type(uint56).max - 1));
+ params.checkpoint2 = uint56(bound(params.checkpoint2, params.checkpoint1 + 1, type(uint56).max));
+ params.snapshotCheckpoint = uint56(bound(params.snapshotCheckpoint, params.checkpoint1, type(uint56).max));
+
+ test_checkpointer_unused_snapshot_chain_vars_fail memory vars;
+
+ vars.signer1addr = vm.addr(params.signerPk1);
+ vars.signer2addr = vm.addr(params.signerPk2);
+
+ vars.config1Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 1,
+ params.checkpoint1,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer1addr), ":1"))
+ );
+ vars.config1ImageHash = PrimitivesRPC.getImageHash(vm, vars.config1Json);
+
+ vars.config2Json = PrimitivesRPC.newConfigWithCheckpointer(
+ vm,
+ params.checkpointer,
+ 2,
+ params.checkpoint2,
+ string(abi.encodePacked("signer:", vm.toString(vars.signer2addr), ":2"))
+ );
+ vars.config2ImageHash = PrimitivesRPC.getImageHash(vm, vars.config2Json);
+
+ vm.assume(params.snapshotImageHash != bytes32(0));
+ vm.assume(params.snapshotImageHash != vars.config1ImageHash);
+ vm.assume(params.snapshotImageHash != vars.config2ImageHash);
+
+ vars.payloadApprove2.kind = Payload.KIND_CONFIG_UPDATE;
+ vars.payloadApprove2.imageHash = vars.config2ImageHash;
+ vars.payloadApprove2.noChainId = true;
+
+ (vars.v1, vars.r1, vars.s1) = vm.sign(params.signerPk1, Payload.hashFor(vars.payloadApprove2, address(baseSigImp)));
+ vars.signature1to2 = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config1Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer1addr),
+ ":hash:",
+ vm.toString(vars.r1),
+ ":",
+ vm.toString(vars.s1),
+ ":",
+ vm.toString(vars.v1)
+ )
+ ),
+ false,
+ params.checkpointerData
+ );
+
+ (vars.v2, vars.r2, vars.s2) = vm.sign(params.signerPk2, Payload.hashFor(params.payload, address(baseSigImp)));
+ vars.signature2toPayload = PrimitivesRPC.toEncodedSignatureWithCheckpointerData(
+ vm,
+ vars.config2Json,
+ string(
+ abi.encodePacked(
+ vm.toString(vars.signer2addr),
+ ":hash:",
+ vm.toString(vars.r2),
+ ":",
+ vm.toString(vars.s2),
+ ":",
+ vm.toString(vars.v2)
+ )
+ ),
+ !params.payload.noChainId,
+ params.checkpointerData
+ );
+
+ vars.snapshot.imageHash = params.snapshotImageHash;
+ vars.snapshot.checkpoint = params.snapshotCheckpoint;
+
+ vm.mockCall(
+ params.checkpointer, abi.encodeWithSelector(ICheckpointer.snapshotFor.selector), abi.encode(vars.snapshot)
+ );
+
+ bytes[] memory signatures = new bytes[](2);
+ signatures[0] = vars.signature2toPayload;
+ signatures[1] = vars.signature1to2;
+ vars.chainedSignature = PrimitivesRPC.concatSignatures(vm, signatures);
+
+ if (params.snapshotImageHash == bytes32(0)) {
+ // Snapshot imageHash is 0, checkpointer is considered disabled
+ (uint256 threshold, uint256 weight, bytes32 imageHash, uint256 checkpoint,) =
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ assertEq(threshold, 1);
+ assertEq(weight, 1);
+ assertEq(imageHash, vars.config1ImageHash);
+ assertEq(checkpoint, params.checkpoint1);
+ } else {
+ vm.expectRevert(abi.encodeWithSelector(BaseSig.UnusedSnapshot.selector, vars.snapshot));
+ baseSigImp.recoverPub(params.payload, vars.chainedSignature, false, address(0));
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Calls.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Calls.t.sol
new file mode 100644
index 000000000..b4f57987e
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Calls.t.sol
@@ -0,0 +1,457 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Calls } from "../../src/modules/Calls.sol";
+
+import { Payload } from "../../src/modules/Payload.sol";
+import { AdvTest } from "../utils/TestUtils.sol";
+
+import { Payload } from "../../src/modules/Payload.sol";
+
+import { PrimitivesRPC } from "../utils/PrimitivesRPC.sol";
+
+contract CallsImp is Calls {
+
+ bytes public expectedSignature;
+ bytes32 public expectedOpHash;
+
+ function setExpectedSignature(
+ bytes calldata _signature
+ ) external {
+ expectedSignature = _signature;
+ }
+
+ function setExpectedOpHash(
+ bytes32 _opHash
+ ) external {
+ expectedOpHash = _opHash;
+ }
+
+ function writeNonce(uint256 _space, uint256 _nonce) external {
+ _writeNonce(_space, _nonce);
+ }
+
+ function signatureValidation(
+ Payload.Decoded memory,
+ bytes calldata _signature
+ ) internal view override returns (bool isValid, bytes32 opHash) {
+ return (keccak256(_signature) == keccak256(expectedSignature), expectedOpHash);
+ }
+
+ function _isValidImage(
+ bytes32
+ ) internal pure override returns (bool) {
+ revert("Not used");
+ }
+
+ function _updateImageHash(
+ bytes32
+ ) internal pure override {
+ revert("Not used");
+ }
+
+}
+
+contract MockDelegatecall { // extends IDelegatedExtension (but we make it payable for the test)
+
+ event OpHash(bytes32 _opHash);
+ event StartingGas(uint256 _startingGas);
+ event Index(uint256 _index);
+ event NumCalls(uint256 _numCalls);
+ event Space(uint256 _space);
+ event Data(bytes _data);
+
+ function handleSequenceDelegateCall(
+ bytes32 _opHash,
+ uint256 _startingGas,
+ uint256 _index,
+ uint256 _numCalls,
+ uint256 _space,
+ bytes calldata _data
+ ) external payable {
+ emit OpHash(_opHash);
+ emit StartingGas(_startingGas);
+ emit Index(_index);
+ emit NumCalls(_numCalls);
+ emit Space(_space);
+ emit Data(_data);
+ }
+
+ receive() external payable { }
+ fallback() external payable { }
+
+}
+
+struct CallsPayload {
+ bool noChainId;
+ Payload.Call[] calls;
+ uint160 space;
+ uint56 nonce;
+}
+
+function toDecodedPayload(
+ CallsPayload memory _payload
+) pure returns (Payload.Decoded memory _decoded) {
+ _decoded.kind = Payload.KIND_TRANSACTIONS;
+ _decoded.calls = _payload.calls;
+ _decoded.space = _payload.space;
+ _decoded.nonce = _payload.nonce;
+}
+
+contract CallsTest is AdvTest {
+
+ CallsImp public calls = new CallsImp();
+
+ event CallSucceeded(bytes32 _opHash, uint256 _index);
+ event CallSkipped(bytes32 _opHash, uint256 _index);
+ event CallFailed(bytes32 _opHash, uint256 _index, bytes _returnData);
+ event CallAborted(bytes32 _opHash, uint256 _index, bytes _returnData);
+
+ function preparePayload(
+ Payload.Decoded memory decoded
+ ) internal {
+ uint256 totalEther;
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ decoded.calls[i].to = boundNoPrecompile(decoded.calls[i].to);
+ decoded.calls[i].value = bound(decoded.calls[i].value, 0, 100_000_000_000_000 ether);
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 0, 1_000_000_000);
+
+ if (!decoded.calls[i].delegateCall && !decoded.calls[i].onlyFallback) {
+ totalEther += decoded.calls[i].value;
+ }
+
+ if (decoded.calls[i].delegateCall && decoded.calls[i].gasLimit != 0) {
+ decoded.calls[i].gasLimit = bound(decoded.calls[i].gasLimit, 100_000, 1_000_000_000);
+ }
+
+ vm.assume(decoded.calls[i].to != address(calls));
+ }
+
+ vm.deal(address(calls), totalEther);
+ }
+
+ function test_execute(bytes32 _opHash, CallsPayload memory _payload, bytes calldata _signature) external {
+ vm.assume(_payload.calls.length < 3);
+ address mockDelegatecall = address(new MockDelegatecall());
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+
+ preparePayload(decoded);
+ boundToLegalPayload(decoded);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ calls.setExpectedSignature(_signature);
+ calls.setExpectedOpHash(_opHash);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ if (decoded.calls[i].onlyFallback) {
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit CallSkipped(_opHash, i);
+ } else {
+ vm.deal(decoded.calls[i].to, 0);
+
+ if (decoded.calls[i].delegateCall) {
+ vm.etch(decoded.calls[i].to, mockDelegatecall.code);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.OpHash(_opHash);
+ // Can't test gasleft() because memory expansion makes it not so reliable
+ // emit MockDelegatecall.StartingGas(gasleft());
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.Index(i);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.NumCalls(decoded.calls.length);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.Space(decoded.space);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.Data(decoded.calls[i].data);
+ } else {
+ vm.expectCall(decoded.calls[i].to, decoded.calls[i].data);
+ }
+
+ emit CallSucceeded(_opHash, i);
+ }
+ }
+
+ calls.execute(packed, _signature);
+
+ assertEq(address(calls).balance, 0);
+
+ // Assert balance of each destination contract
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ if (
+ !decoded.calls[i].delegateCall && decoded.calls[i].to.balance != decoded.calls[i].value
+ && !decoded.calls[i].onlyFallback
+ ) {
+ // We need to do a full recount because maybe the contract is duplicated so multiple transfers are done
+ uint256 totalTransferred = 0;
+ for (uint256 j = 0; j < decoded.calls.length; j++) {
+ if (
+ !decoded.calls[j].delegateCall && decoded.calls[j].to == decoded.calls[i].to
+ && !decoded.calls[j].onlyFallback
+ ) {
+ totalTransferred += decoded.calls[j].value;
+ }
+ }
+ assertEq(totalTransferred, decoded.calls[i].to.balance);
+ }
+ }
+ }
+
+ function test_self_execute(
+ CallsPayload memory _payload
+ ) external {
+ vm.assume(_payload.calls.length < 3);
+ address mockDelegatecall = address(new MockDelegatecall());
+
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+
+ preparePayload(decoded);
+ boundToLegalPayload(decoded);
+
+ bytes32 opHash = Payload.hashFor(decoded, address(calls));
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ if (decoded.calls[i].onlyFallback) {
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit CallSkipped(opHash, i);
+ } else {
+ vm.deal(decoded.calls[i].to, 0);
+ if (decoded.calls[i].delegateCall) {
+ vm.etch(decoded.calls[i].to, mockDelegatecall.code);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.OpHash(opHash);
+ // Can't reliably test gasleft() due to memory expansion changes
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.Index(i);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.NumCalls(decoded.calls.length);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.Space(decoded.space);
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit MockDelegatecall.Data(decoded.calls[i].data);
+ } else {
+ vm.expectCall(decoded.calls[i].to, decoded.calls[i].data);
+ }
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit CallSucceeded(opHash, i);
+ }
+ }
+
+ vm.prank(address(calls));
+ calls.selfExecute(packed);
+
+ assertEq(address(calls).balance, 0);
+
+ for (uint256 i = 0; i < decoded.calls.length; i++) {
+ if (
+ !decoded.calls[i].delegateCall && decoded.calls[i].to.balance != decoded.calls[i].value
+ && !decoded.calls[i].onlyFallback
+ ) {
+ uint256 totalTransferred = 0;
+ for (uint256 j = 0; j < decoded.calls.length; j++) {
+ if (
+ !decoded.calls[j].delegateCall && decoded.calls[j].to == decoded.calls[i].to
+ && !decoded.calls[j].onlyFallback
+ ) {
+ totalTransferred += decoded.calls[j].value;
+ }
+ }
+ assertEq(totalTransferred, decoded.calls[i].to.balance);
+ }
+ }
+ }
+
+ function test_invalid_signature(
+ CallsPayload memory _payload,
+ bytes calldata _signature,
+ bytes calldata _wrongSignature
+ ) external {
+ vm.assume(_signature.length > 0 && _wrongSignature.length > 0);
+ vm.assume(keccak256(_signature) != keccak256(_wrongSignature));
+
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+ boundToLegalPayload(decoded);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(calls));
+
+ calls.setExpectedSignature(_signature);
+ calls.setExpectedOpHash(opHash);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ vm.expectRevert(abi.encodeWithSelector(Calls.InvalidSignature.selector, decoded, _wrongSignature));
+ calls.execute(packed, _wrongSignature);
+ }
+
+ function test_error_flag_behavior(
+ Payload.Call calldata call1,
+ Payload.Call calldata call2,
+ bytes calldata _signature
+ ) external {
+ CallsPayload memory _payload;
+ _payload.calls = new Payload.Call[](2);
+
+ // Set up the first call to fail
+ _payload.calls[0] = call1;
+ _payload.calls[0].onlyFallback = false;
+ _payload.calls[0].delegateCall = false;
+ _payload.calls[0].behaviorOnError = Payload.BEHAVIOR_IGNORE_ERROR;
+
+ // Set up the second call to be a fallback call
+ _payload.calls[1] = call2;
+ _payload.calls[1].onlyFallback = true;
+
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+ preparePayload(decoded);
+ boundToLegalPayload(decoded);
+
+ // Ensure we have enough ether for both calls, even though the second one will be skipped
+ uint256 totalEther = decoded.calls[0].value + decoded.calls[1].value;
+ vm.deal(address(calls), totalEther);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(calls));
+
+ calls.setExpectedSignature(_signature);
+ calls.setExpectedOpHash(opHash);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ bytes memory revertData = abi.encodeWithSelector(bytes4(keccak256("revert()")));
+
+ // Force the first call to fail by making it revert
+ vm.mockCallRevert(_payload.calls[0].to, _payload.calls[0].value, _payload.calls[0].data, revertData);
+
+ // First call should fail and emit CallFailed
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit CallFailed(opHash, 0, revertData);
+
+ // Second call should succeed as the previous error makes the fallback execute
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit CallSucceeded(opHash, 1);
+
+ calls.execute(packed, _signature);
+ }
+
+ function test_revert_on_error(Payload.Call calldata call, bytes calldata _signature) external {
+ CallsPayload memory _payload;
+ _payload.calls = new Payload.Call[](1);
+
+ // Set up the call to fail
+ _payload.calls[0] = call;
+ _payload.calls[0].onlyFallback = false;
+ _payload.calls[0].delegateCall = false;
+ _payload.calls[0].behaviorOnError = Payload.BEHAVIOR_REVERT_ON_ERROR;
+
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+ preparePayload(decoded);
+ boundToLegalPayload(decoded);
+
+ // Ensure we have enough ether
+ vm.deal(address(calls), decoded.calls[0].value);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(calls));
+
+ calls.setExpectedSignature(_signature);
+ calls.setExpectedOpHash(opHash);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ bytes memory revertData = abi.encodeWithSelector(bytes4(keccak256("revert()")));
+
+ // Force the call to fail by making it revert
+ vm.mockCallRevert(_payload.calls[0].to, _payload.calls[0].value, _payload.calls[0].data, revertData);
+
+ // Expect the call to revert with Reverted error
+ vm.expectRevert(abi.encodeWithSelector(Calls.Reverted.selector, decoded, 0, revertData));
+
+ calls.execute(packed, _signature);
+ }
+
+ function test_abort_on_error(Payload.Call calldata call, bytes calldata _signature) external {
+ CallsPayload memory _payload;
+ _payload.calls = new Payload.Call[](1);
+
+ // Set up the call to fail
+ _payload.calls[0] = call;
+ _payload.calls[0].onlyFallback = false;
+ _payload.calls[0].delegateCall = false;
+ _payload.calls[0].behaviorOnError = Payload.BEHAVIOR_ABORT_ON_ERROR;
+
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+ preparePayload(decoded);
+ boundToLegalPayload(decoded);
+
+ // Ensure we have enough ether
+ vm.deal(address(calls), decoded.calls[0].value);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(calls));
+
+ calls.setExpectedSignature(_signature);
+ calls.setExpectedOpHash(opHash);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ bytes memory revertData = abi.encodeWithSelector(bytes4(keccak256("revert()")));
+
+ // Force the call to fail by making it revert
+ vm.mockCallRevert(_payload.calls[0].to, _payload.calls[0].value, _payload.calls[0].data, revertData);
+
+ // Call should fail and emit CallAborted
+ vm.expectEmit(true, true, true, true, address(calls));
+ emit CallAborted(opHash, 0, revertData);
+
+ calls.execute(packed, _signature);
+ }
+
+ function test_not_enough_gas(Payload.Call calldata call, uint256 txGasLimit, bytes calldata _signature) external {
+ CallsPayload memory _payload;
+ _payload.calls = new Payload.Call[](1);
+
+ txGasLimit = bound(txGasLimit, 1_000_000, 999_999_999);
+
+ // Set up the call with a high gas limit
+ _payload.calls[0] = call;
+ _payload.calls[0].onlyFallback = false;
+ _payload.calls[0].delegateCall = false;
+ _payload.calls[0].gasLimit = bound(call.gasLimit, txGasLimit, 1_000_000_000);
+
+ Payload.Decoded memory decoded = toDecodedPayload(_payload);
+ preparePayload(decoded);
+ boundToLegalPayload(decoded);
+
+ // Ensure we have enough ether
+ vm.deal(address(calls), decoded.calls[0].value);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ bytes32 opHash = Payload.hashFor(decoded, address(calls));
+
+ calls.setExpectedSignature(_signature);
+ calls.setExpectedOpHash(opHash);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ // Expect the call to revert with NotEnoughGas error. We do not expect the exact gas left
+ vm.expectPartialRevert(Calls.NotEnoughGas.selector);
+
+ calls.execute{ gas: txGasLimit }(packed, _signature);
+ }
+
+ function test_empty_payload_consumes_nonce(uint256 space, uint256 nonce, bytes calldata signature) external {
+ Payload.Decoded memory decoded;
+ decoded.kind = Payload.KIND_TRANSACTIONS;
+ decoded.space = space;
+ decoded.nonce = nonce;
+ boundToLegalPayload(decoded);
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, decoded);
+ calls.writeNonce(decoded.space, decoded.nonce);
+
+ calls.setExpectedSignature(signature);
+ calls.setExpectedOpHash(keccak256(packed));
+
+ calls.execute(packed, signature);
+ assertEq(calls.readNonce(decoded.space), decoded.nonce + 1);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/ERC4337v07.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/ERC4337v07.t.sol
new file mode 100644
index 000000000..c011187cd
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/ERC4337v07.t.sol
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Factory } from "../../src/Factory.sol";
+import { Stage1Module } from "../../src/Stage1Module.sol";
+import { Calls } from "../../src/modules/Calls.sol";
+
+import { ERC4337v07 } from "../../src/modules/ERC4337v07.sol";
+import { Payload } from "../../src/modules/Payload.sol";
+import { PackedUserOperation } from "../../src/modules/interfaces/IAccount.sol";
+
+import { CanReenter } from "../mocks/CanReenter.sol";
+import { Emitter } from "../mocks/Emitter.sol";
+import { PrimitivesRPC } from "../utils/PrimitivesRPC.sol";
+import { AdvTest } from "../utils/TestUtils.sol";
+import { EntryPoint, IStakeManager } from "account-abstraction/core/EntryPoint.sol";
+
+contract ERC4337v07Test is AdvTest {
+
+ Factory public factory;
+ EntryPoint public entryPoint;
+ Stage1Module public stage1Module;
+ address payable public wallet;
+ string public walletConfig;
+ bytes32 public walletImageHash;
+ uint256 public signerPk;
+ address public signer;
+
+ function setUp() public {
+ factory = new Factory();
+ entryPoint = new EntryPoint();
+ stage1Module = new Stage1Module(address(factory), address(entryPoint));
+
+ // Basic wallet setup for most tests.
+ signerPk = boundPk(123);
+ signer = vm.addr(signerPk);
+ walletConfig = PrimitivesRPC.newConfig(vm, 1, 0, string(abi.encodePacked("signer:", vm.toString(signer), ":1")));
+ walletImageHash = PrimitivesRPC.getImageHash(vm, walletConfig);
+ wallet = payable(factory.deploy(address(stage1Module), walletImageHash));
+ }
+
+ // --- Helper Functions ---
+
+ function _createUserOp(
+ bytes memory _callData,
+ bytes memory _signature
+ ) internal view returns (PackedUserOperation memory) {
+ return PackedUserOperation({
+ sender: wallet,
+ nonce: 0, // Nonce is validated by the real entrypoint, not the account.
+ initCode: "",
+ callData: _callData,
+ accountGasLimits: bytes32(0),
+ preVerificationGas: 21000,
+ gasFees: bytes32(0),
+ paymasterAndData: "",
+ signature: _signature
+ });
+ }
+
+ // --- validateUserOp Tests ---
+
+ function test_validateUserOp_reverts_if_disabled(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingFunds
+ ) public {
+ // Deploy a new wallet with 4337 disabled (entrypoint is address(0)).
+ Stage1Module moduleDisabled = new Stage1Module(address(factory), address(0));
+ address payable walletDisabled = payable(factory.deploy(address(moduleDisabled), walletImageHash));
+
+ vm.prank(address(entryPoint));
+ vm.expectRevert(ERC4337v07.ERC4337Disabled.selector);
+ Stage1Module(walletDisabled).validateUserOp(userOp, userOpHash, missingFunds);
+ }
+
+ function test_validateUserOp_reverts_invalidEntryPoint(
+ PackedUserOperation calldata userOp,
+ bytes32 userOpHash,
+ uint256 missingFunds,
+ address randomCaller
+ ) public {
+ vm.assume(randomCaller != address(entryPoint));
+
+ vm.prank(randomCaller);
+ vm.expectRevert(abi.encodeWithSelector(ERC4337v07.InvalidEntryPoint.selector, randomCaller));
+ Stage1Module(wallet).validateUserOp(userOp, userOpHash, missingFunds);
+ }
+
+ function test_validateUserOp_depositsMissingFunds(bytes32 userOpHash, uint256 missingFunds) public {
+ vm.assume(missingFunds > 0);
+ // Signature doesn't need to be valid for this test.
+ PackedUserOperation memory userOp = _createUserOp(bytes(""), hex"000010000000000000000000000000000000000000000000");
+
+ // The wallet needs the funds *before* the call to be able to deposit them,
+ // as validateUserOp is not payable.
+ vm.deal(wallet, missingFunds);
+
+ vm.prank(address(entryPoint));
+
+ vm.expectEmit(true, true, false, true, address(entryPoint));
+ emit IStakeManager.Deposited(wallet, missingFunds);
+
+ // Call validateUserOp without sending value. The wallet will use its own balance to deposit.
+ uint256 validationData = Stage1Module(wallet).validateUserOp(userOp, userOpHash, missingFunds);
+
+ assertEq(validationData, 1, "Should return 1 for signature failure");
+ assertEq(entryPoint.balanceOf(wallet), missingFunds, "Missing funds were not deposited correctly");
+ assertEq(address(wallet).balance, 0, "Wallet should have used its balance for the deposit");
+ }
+
+ function test_validateUserOp_returns_zero_on_validSignature(
+ bytes32 userOpHash
+ ) public {
+ // Create a signature for the userOpHash using the wallet's signer config.
+ Payload.Decoded memory payload;
+ payload.kind = Payload.KIND_DIGEST;
+ payload.digest = userOpHash;
+
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPk, Payload.hashFor(payload, wallet));
+ string memory signatures =
+ string(abi.encodePacked(vm.toString(signer), ":hash:", vm.toString(r), ":", vm.toString(s), ":", vm.toString(v)));
+ bytes memory encodedSignature = PrimitivesRPC.toEncodedSignature(vm, walletConfig, signatures, true);
+
+ PackedUserOperation memory userOp = _createUserOp(bytes(""), encodedSignature);
+
+ vm.prank(address(entryPoint));
+ uint256 validationData = Stage1Module(wallet).validateUserOp(userOp, userOpHash, 0);
+
+ assertEq(validationData, 0, "Should return 0 for a valid signature");
+ }
+
+ function test_validateUserOp_returns_one_on_invalidSignature(
+ bytes32 userOpHash
+ ) public {
+ // Use a random, invalid signature provided by the fuzzer.
+ PackedUserOperation memory userOp = _createUserOp(bytes(""), hex"000010000000000000000000000000000000000000000000");
+
+ vm.prank(address(entryPoint));
+ uint256 validationData = Stage1Module(wallet).validateUserOp(userOp, userOpHash, 0);
+
+ assertEq(validationData, 1, "Should return 1 (SIG_VALIDATION_FAILED) for an invalid signature");
+ }
+
+ // --- executeUserOp Tests ---
+
+ function test_executeUserOp_reverts_if_disabled(
+ bytes calldata payload
+ ) public {
+ // Deploy a new wallet with 4337 disabled.
+ Stage1Module moduleDisabled = new Stage1Module(address(factory), address(0));
+ address payable walletDisabled = payable(factory.deploy(address(moduleDisabled), walletImageHash));
+
+ vm.prank(address(entryPoint));
+ vm.expectRevert(ERC4337v07.ERC4337Disabled.selector);
+ Stage1Module(walletDisabled).executeUserOp(payload);
+ }
+
+ function test_executeUserOp_reverts_invalidEntryPoint(bytes calldata payload, address randomCaller) public {
+ vm.assume(randomCaller != address(entryPoint));
+
+ vm.prank(randomCaller);
+ vm.expectRevert(abi.encodeWithSelector(ERC4337v07.InvalidEntryPoint.selector, randomCaller));
+ Stage1Module(wallet).executeUserOp(payload);
+ }
+
+ function test_executeUserOp_executes_payload() external {
+ // Setup a mock contract to call.
+ Emitter emitter = new Emitter();
+
+ // Create a payload to call the emitter contract.
+ Payload.Decoded memory decodedPayload;
+ decodedPayload.kind = Payload.KIND_TRANSACTIONS;
+ decodedPayload.calls = new Payload.Call[](1);
+ decodedPayload.calls[0] = Payload.Call({
+ to: address(emitter),
+ value: 0,
+ data: abi.encodeWithSelector(Emitter.explicitEmit.selector),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_REVERT_ON_ERROR
+ });
+
+ bytes memory packedPayload = PrimitivesRPC.toPackedPayload(vm, decodedPayload);
+
+ // Expect the call to succeed and the event to be emitted from the Emitter contract.
+ vm.expectEmit(true, false, false, true, address(emitter));
+ emit Emitter.Explicit(wallet);
+
+ // Execute the userOp via the entrypoint.
+ vm.prank(address(entryPoint));
+ Stage1Module(wallet).executeUserOp(packedPayload);
+ }
+
+ function test_executeUserOp_protected_from_reentry() external {
+ // Setup a mock contract that can attempt reentry
+ CanReenter canReenter = new CanReenter();
+
+ // Create an inner payload that will be called during reentry
+ Payload.Decoded memory innerPayload;
+ innerPayload.kind = Payload.KIND_TRANSACTIONS;
+ innerPayload.calls = new Payload.Call[](1);
+ innerPayload.calls[0] = Payload.Call({
+ to: address(0x123), // Some target
+ value: 0,
+ data: bytes(""),
+ gasLimit: 0,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_IGNORE_ERROR
+ });
+
+ // Pack the inner payload
+ bytes memory innerPackedPayload = PrimitivesRPC.toPackedPayload(vm, innerPayload);
+
+ // Create an outer payload that calls the canReenter contract
+ Payload.Decoded memory outerPayload;
+ outerPayload.kind = Payload.KIND_TRANSACTIONS;
+ outerPayload.calls = new Payload.Call[](1);
+ outerPayload.calls[0] = Payload.Call({
+ to: address(canReenter),
+ value: 0,
+ data: abi.encodeWithSelector(
+ CanReenter.doAnotherCall.selector,
+ address(wallet),
+ abi.encodeWithSelector(Stage1Module(wallet).executeUserOp.selector, innerPackedPayload)
+ ),
+ gasLimit: 1000000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_IGNORE_ERROR
+ });
+
+ // Pack the outer payload
+ bytes memory outerPackedPayload = PrimitivesRPC.toPackedPayload(vm, outerPayload);
+
+ // Execute the outer payload
+ bytes32 outerHash = Payload.hashFor(outerPayload, wallet);
+ vm.expectEmit(true, true, true, true, address(wallet));
+ emit Calls.CallFailed(outerHash, 0, abi.encodeWithSelector(bytes4(keccak256("Error(string)")), "Call failed"));
+ vm.prank(address(entryPoint));
+ Stage1Module(wallet).executeUserOp(outerPackedPayload);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Hooks.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Hooks.t.sol
new file mode 100644
index 000000000..b4161a03f
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Hooks.t.sol
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Factory } from "../../src/Factory.sol";
+import { Hooks, IERC1155Receiver, IERC223Receiver, IERC721Receiver, IERC777Receiver } from "../../src/modules/Hooks.sol";
+import { SelfAuth } from "../../src/modules/auth/SelfAuth.sol";
+
+import { AdvTest } from "../utils/TestUtils.sol";
+
+contract HooksTest is AdvTest {
+
+ Hooks public hooks;
+ address public constant TEST_IMPLEMENTATION = address(0x123);
+ Factory public factory;
+
+ function setUp() public {
+ // Deploy via factory to test forwarding
+ Hooks impl = new Hooks();
+ factory = new Factory();
+ hooks = Hooks(payable(factory.deploy(address(impl), bytes32(0))));
+ }
+
+ // Hook Management Tests
+ function test_addHook() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ vm.prank(address(hooks));
+ hooks.addHook(signature, TEST_IMPLEMENTATION);
+ assertEq(hooks.readHook(signature), TEST_IMPLEMENTATION);
+ }
+
+ function test_addHook_revertWhenHookExists() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ vm.prank(address(hooks));
+ hooks.addHook(signature, TEST_IMPLEMENTATION);
+ vm.expectRevert(abi.encodeWithSelector(Hooks.HookAlreadyExists.selector, signature));
+ vm.prank(address(hooks));
+ hooks.addHook(signature, TEST_IMPLEMENTATION);
+ }
+
+ function test_addHook_revertWhenNotSelf() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ vm.expectRevert(abi.encodeWithSelector(SelfAuth.OnlySelf.selector, address(this)));
+ hooks.addHook(signature, TEST_IMPLEMENTATION);
+ }
+
+ function test_removeHook() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ vm.prank(address(hooks));
+ hooks.addHook(signature, TEST_IMPLEMENTATION);
+ vm.prank(address(hooks));
+ hooks.removeHook(signature);
+ assertEq(hooks.readHook(signature), address(0));
+ }
+
+ function test_removeHook_revertWhenHookDoesNotExist() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ vm.expectRevert(abi.encodeWithSelector(Hooks.HookDoesNotExist.selector, signature));
+ vm.prank(address(hooks));
+ hooks.removeHook(signature);
+ }
+
+ // ERC1155 Receiver Tests
+ function test_onERC1155Received(
+ address _from,
+ address _to,
+ uint256 _id,
+ uint256 _value,
+ bytes calldata _data
+ ) external view {
+ bytes4 selector = IERC1155Receiver.onERC1155Received.selector;
+ assertEq(selector, bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)")));
+ bytes4 returnValue = hooks.onERC1155Received(_from, _to, _id, _value, _data);
+ assertEq(returnValue, selector);
+ }
+
+ function test_onERC1155BatchReceived(
+ address _from,
+ address _to,
+ uint256[] calldata _ids,
+ uint256[] calldata _values,
+ bytes calldata _data
+ ) external view {
+ bytes4 selector = IERC1155Receiver.onERC1155BatchReceived.selector;
+ assertEq(selector, bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)")));
+ bytes4 returnValue = hooks.onERC1155BatchReceived(_from, _to, _ids, _values, _data);
+ assertEq(returnValue, selector);
+ }
+
+ // ERC777 Receiver Tests
+ function test_tokensReceived(
+ address _operator,
+ address _from,
+ address _to,
+ uint256 _amount,
+ bytes calldata _data,
+ bytes calldata _operatorData
+ ) public {
+ bytes4 selector = IERC777Receiver.tokensReceived.selector;
+ assertEq(selector, bytes4(keccak256("tokensReceived(address,address,address,uint256,bytes,bytes)")));
+ hooks.tokensReceived(_operator, _from, _to, _amount, _data, _operatorData);
+ }
+
+ // ERC721 Receiver Tests
+ function test_onERC721Received(address _from, address _to, uint256 _tokenId, bytes calldata _data) external view {
+ bytes4 selector = IERC721Receiver.onERC721Received.selector;
+ assertEq(selector, bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")));
+ bytes4 returnValue = hooks.onERC721Received(_from, _to, _tokenId, _data);
+ assertEq(returnValue, selector);
+ }
+
+ // ERC223 Receiver Tests
+ function test_tokenReceived(address _from, uint256 _value, bytes calldata _data) external view {
+ bytes4 selector = IERC223Receiver.tokenReceived.selector;
+ assertEq(selector, bytes4(keccak256("tokenReceived(address,uint256,bytes)")));
+ bytes4 returnValue = hooks.tokenReceived(_from, _value, _data);
+ assertEq(returnValue, selector);
+ }
+
+ // Fallback and Receive Tests
+ function test_fallback() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ address mockImplementation = address(new MockImplementation());
+ vm.prank(address(hooks));
+ hooks.addHook(signature, mockImplementation);
+
+ (bool success, bytes memory result) = address(hooks).call(abi.encodeWithSelector(signature));
+ assertTrue(success);
+ assertEq(result, abi.encode(true));
+
+ success = MockImplementation(address(hooks)).testFunction();
+ assertTrue(success);
+ }
+
+ function test_fallbackRevertWhenHookNotPayable() public {
+ bytes4 signature = bytes4(keccak256("testFunction()"));
+ address mockImplementation = address(new MockImplementation());
+ vm.prank(address(hooks));
+ hooks.addHook(signature, mockImplementation);
+
+ (bool success,) = address(hooks).call{ value: 1 ether }(abi.encodeWithSelector(signature));
+ assertFalse(success);
+ }
+
+ function test_payableFallback() public {
+ bytes4 signature = bytes4(keccak256("testPayableFunction()"));
+ address mockImplementation = address(new MockImplementation());
+ vm.prank(address(hooks));
+ hooks.addHook(signature, mockImplementation);
+
+ (bool success, bytes memory result) = address(hooks).call{ value: 1 ether }(abi.encodeWithSelector(signature));
+ assertTrue(success);
+ assertEq(result, abi.encode(true));
+ assertEq(address(hooks).balance, 1 ether);
+ }
+
+ function test_receive() public {
+ vm.deal(address(this), 1 ether);
+ (bool success,) = address(hooks).call{ value: 1 ether }("");
+ assertTrue(success);
+ }
+
+}
+
+contract MockImplementation {
+
+ function testFunction() external pure returns (bool) {
+ return true;
+ }
+
+ function testPayableFunction() external payable returns (bool) {
+ return true;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Implementation.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Implementation.t.sol
new file mode 100644
index 000000000..a3ecc0d2a
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Implementation.t.sol
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Implementation } from "../../src/modules/Implementation.sol";
+import { SelfAuth } from "../../src/modules/auth/SelfAuth.sol";
+
+import { AdvTest } from "../utils/TestUtils.sol";
+import { Vm } from "forge-std/Test.sol";
+
+contract ImplementationTest is AdvTest {
+
+ Implementation public implementation;
+
+ function setUp() public {
+ implementation = new Implementation();
+ }
+
+ function test_updateImplementation(
+ address _implementation
+ ) public {
+ vm.prank(address(implementation));
+ implementation.updateImplementation(_implementation);
+ assertEq(implementation.getImplementation(), _implementation);
+ }
+
+ function test_updateImplementation_revertWhenNotSelf() public {
+ vm.expectRevert(abi.encodeWithSelector(SelfAuth.OnlySelf.selector, address(this)));
+ implementation.updateImplementation(address(this));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Nonce.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Nonce.t.sol
new file mode 100644
index 000000000..878b2f6e1
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Nonce.t.sol
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Nonce } from "../../src/modules/Nonce.sol";
+import { SelfAuth } from "../../src/modules/auth/SelfAuth.sol";
+
+import { AdvTest } from "../utils/TestUtils.sol";
+import { Vm } from "forge-std/Test.sol";
+
+contract NonceImp is Nonce {
+
+ function writeNonce(uint256 _space, uint256 _nonce) public {
+ super._writeNonce(_space, _nonce);
+ }
+
+ function consumeNonce(uint256 _space, uint256 _nonce) public {
+ super._consumeNonce(_space, _nonce);
+ }
+
+}
+
+contract NonceTest is AdvTest {
+
+ NonceImp public nonceImp;
+
+ function setUp() public {
+ nonceImp = new NonceImp();
+ }
+
+ function test_readNonce(uint256 _space, uint256 _nonce) public {
+ nonceImp.writeNonce(_space, _nonce);
+ assertEq(nonceImp.readNonce(_space), _nonce);
+ }
+
+ function test_consumeNonce(uint256 _space, uint256 _nonce) public {
+ vm.assume(_nonce < type(uint256).max - 1);
+ nonceImp.writeNonce(_space, _nonce);
+ nonceImp.consumeNonce(_space, _nonce);
+ assertEq(nonceImp.readNonce(_space), _nonce + 1);
+ }
+
+ function test_consumeNonce_revertWhenBadNonce(uint256 _space, uint256 _nonce, uint256 _badNonce) public {
+ vm.assume(_nonce < type(uint256).max - 1);
+ vm.assume(_badNonce != _nonce);
+ nonceImp.writeNonce(_space, _nonce);
+ vm.expectRevert(abi.encodeWithSelector(Nonce.BadNonce.selector, _space, _badNonce, _nonce));
+ nonceImp.consumeNonce(_space, _badNonce);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Payload.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Payload.t.sol
new file mode 100644
index 000000000..061902225
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/modules/Payload.t.sol
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../src/modules/Payload.sol";
+import { PrimitivesRPC } from "../utils/PrimitivesRPC.sol";
+
+import { AdvTest } from "../utils/TestUtils.sol";
+import { Test, Vm } from "forge-std/Test.sol";
+import { console } from "forge-std/console.sol";
+
+contract PayloadImp {
+
+ function fromMessage(
+ bytes calldata message
+ ) external pure returns (Payload.Decoded memory) {
+ return Payload.fromMessage(message);
+ }
+
+ function fromDigest(
+ bytes32 digest
+ ) external pure returns (Payload.Decoded memory) {
+ return Payload.fromDigest(digest);
+ }
+
+ function fromConfigUpdate(
+ bytes32 imageHash
+ ) external pure returns (Payload.Decoded memory) {
+ return Payload.fromConfigUpdate(imageHash);
+ }
+
+ function fromPackedCalls(
+ bytes calldata packed
+ ) external view returns (Payload.Decoded memory) {
+ return Payload.fromPackedCalls(packed);
+ }
+
+ // Expose this otherwise forge won't catch the revert due to depth
+ function toEIP712(
+ Payload.Decoded memory payload
+ ) external pure returns (bytes32) {
+ return Payload.toEIP712(payload);
+ }
+
+ function hash(
+ Payload.Decoded memory payload
+ ) external view returns (bytes32) {
+ return Payload.hash(payload);
+ }
+
+}
+
+contract PayloadTest is AdvTest {
+
+ PayloadImp public payloadImp;
+
+ function setUp() public {
+ payloadImp = new PayloadImp();
+ }
+
+ function test_fromPackedCalls(Payload.Call[] memory _calls, uint256 _space, uint256 _nonce) external {
+ // Convert nonce into legal range
+ _nonce = bound(_nonce, 0, type(uint56).max);
+ _space = bound(_space, 0, type(uint160).max);
+
+ for (uint256 i = 0; i < _calls.length; i++) {
+ // Convert behaviors into legal ones
+ _calls[i].behaviorOnError = bound(
+ _calls[i].behaviorOnError, uint256(Payload.BEHAVIOR_IGNORE_ERROR), uint256(Payload.BEHAVIOR_ABORT_ON_ERROR)
+ );
+ }
+
+ Payload.Decoded memory input;
+ input.kind = Payload.KIND_TRANSACTIONS;
+ input.calls = _calls;
+ input.space = _space;
+ input.nonce = _nonce;
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, input);
+ console.logBytes(packed);
+
+ Payload.Decoded memory output = payloadImp.fromPackedCalls(packed);
+ console.logBytes(abi.encode(output));
+
+ // Input should equal output
+ assertEq(abi.encode(input), abi.encode(output));
+ }
+
+ function test_fromPackedCalls_2bytes(
+ Payload.Call memory _call
+ ) external {
+ // Convert behaviors into legal ones
+ _call.behaviorOnError =
+ bound(_call.behaviorOnError, uint256(Payload.BEHAVIOR_IGNORE_ERROR), uint256(Payload.BEHAVIOR_ABORT_ON_ERROR));
+
+ Payload.Call[] memory _calls = new Payload.Call[](257);
+ for (uint256 i = 0; i < 257; i++) {
+ // Force > 1 byte of calls
+ _calls[i] = _call;
+ }
+
+ Payload.Decoded memory input;
+ input.kind = Payload.KIND_TRANSACTIONS;
+ input.calls = _calls;
+
+ bytes memory packed = PrimitivesRPC.toPackedPayload(vm, input);
+ Payload.Decoded memory output = payloadImp.fromPackedCalls(packed);
+ assertEq(abi.encode(input), abi.encode(output));
+ }
+
+ function test_fromPackedCalls_self(
+ Payload.Call memory _call
+ ) external {
+ // Convert behaviors into legal ones
+ _call.behaviorOnError =
+ bound(_call.behaviorOnError, uint256(Payload.BEHAVIOR_IGNORE_ERROR), uint256(Payload.BEHAVIOR_ABORT_ON_ERROR));
+ _call.to = address(payloadImp);
+
+ Payload.Call[] memory _calls = new Payload.Call[](1);
+ _calls[0] = _call;
+
+ Payload.Decoded memory input;
+ input.kind = Payload.KIND_TRANSACTIONS;
+ input.calls = _calls;
+
+ bytes memory packed = PrimitivesRPC.toPackedPayloadForWallet(vm, input, address(payloadImp));
+ Payload.Decoded memory output = payloadImp.fromPackedCalls(packed);
+ assertEq(abi.encode(input), abi.encode(output));
+ }
+
+ function test_fromMessage(
+ bytes calldata _message
+ ) external view {
+ Payload.Decoded memory _expected;
+ _expected.kind = Payload.KIND_MESSAGE;
+ _expected.message = _message;
+
+ Payload.Decoded memory _actual = payloadImp.fromMessage(_message);
+ assertEq(abi.encode(_expected), abi.encode(_actual));
+ }
+
+ function test_fromDigest(
+ bytes32 _digest
+ ) external view {
+ Payload.Decoded memory _expected;
+ _expected.kind = Payload.KIND_DIGEST;
+ _expected.digest = _digest;
+
+ Payload.Decoded memory _actual = payloadImp.fromDigest(_digest);
+ assertEq(abi.encode(_expected), abi.encode(_actual));
+ }
+
+ function test_fromConfigUpdate(
+ bytes32 _imageHash
+ ) external view {
+ Payload.Decoded memory _expected;
+ _expected.kind = Payload.KIND_CONFIG_UPDATE;
+ _expected.imageHash = _imageHash;
+
+ Payload.Decoded memory _actual = payloadImp.fromConfigUpdate(_imageHash);
+ assertEq(abi.encode(_expected), abi.encode(_actual));
+ }
+
+ // TODO: Re-enable this after the SDK gains support for the digest kind
+ // function test_hashFor_kindDigest(
+ // bytes32 _digest
+ // ) external {
+ // Payload.Decoded memory _payload;
+ // _payload.kind = Payload.KIND_DIGEST;
+ // _payload.digest = _digest;
+ // bytes32 contractHash = Payload.hashFor(_payload, address(this));
+ // bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, address(this), uint64(block.chainid), _payload);
+ // assertEq(contractHash, payloadHash);
+ // }
+
+ function test_hash_kindMessage(bytes calldata _message, address[] memory _parents) external {
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_MESSAGE;
+ _payload.message = _message;
+ _payload.parentWallets = _parents;
+ bytes32 contractHash = payloadImp.hash(_payload);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, address(payloadImp), uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hashFor_kindMessage(bytes calldata _message, address[] memory _parents, address _wallet) external {
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_MESSAGE;
+ _payload.message = _message;
+ _payload.parentWallets = _parents;
+ bytes32 contractHash = Payload.hashFor(_payload, _wallet);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, _wallet, uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hash_kindMessage_as_digest(bytes calldata _message, address[] memory _parents) external {
+ bytes32 digest = keccak256(_message);
+ Payload.Decoded memory _payloadDigest;
+ _payloadDigest.kind = Payload.KIND_DIGEST;
+ _payloadDigest.digest = digest;
+ _payloadDigest.parentWallets = _parents;
+ Payload.Decoded memory _payloadMessage;
+ _payloadMessage.kind = Payload.KIND_MESSAGE;
+ _payloadMessage.message = _message;
+ _payloadMessage.parentWallets = _parents;
+ bytes32 contractHashDigest = payloadImp.hash(_payloadDigest);
+ bytes32 payloadHashMessage =
+ PrimitivesRPC.hashForPayload(vm, address(payloadImp), uint64(block.chainid), _payloadMessage);
+ assertEq(contractHashDigest, payloadHashMessage);
+ }
+
+ function test_hashFor_kindMessage_as_digest(
+ bytes calldata _message,
+ address[] memory _parents,
+ address _wallet
+ ) external {
+ bytes32 digest = keccak256(_message);
+ Payload.Decoded memory _payloadDigest;
+ _payloadDigest.kind = Payload.KIND_DIGEST;
+ _payloadDigest.digest = digest;
+ _payloadDigest.parentWallets = _parents;
+ Payload.Decoded memory _payloadMessage;
+ _payloadMessage.kind = Payload.KIND_MESSAGE;
+ _payloadMessage.message = _message;
+ _payloadMessage.parentWallets = _parents;
+ bytes32 contractHashDigest = Payload.hashFor(_payloadDigest, _wallet);
+ bytes32 payloadHashMessage = PrimitivesRPC.hashForPayload(vm, _wallet, uint64(block.chainid), _payloadMessage);
+ assertEq(contractHashDigest, payloadHashMessage);
+ }
+
+ function test_hash_kindConfigUpdate(bytes32 _imageHash, address[] memory _parents) external {
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_CONFIG_UPDATE;
+ _payload.imageHash = _imageHash;
+ _payload.parentWallets = _parents;
+ bytes32 contractHash = payloadImp.hash(_payload);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, address(payloadImp), uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hashFor_kindConfigUpdate(bytes32 _imageHash, address[] memory _parents, address _wallet) external {
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_CONFIG_UPDATE;
+ _payload.imageHash = _imageHash;
+ _payload.parentWallets = _parents;
+ bytes32 contractHash = Payload.hashFor(_payload, _wallet);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, _wallet, uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hash_kindTransactions(
+ address _to,
+ uint256 _value,
+ bytes memory _data,
+ uint256 _gasLimit,
+ bool _delegateCall,
+ bool _onlyFallback,
+ uint256 _behaviorOnError,
+ uint256 _space,
+ uint256 _nonce,
+ address[] memory _parents
+ ) external {
+ // Convert nonce into legal range
+ _nonce = bound(_nonce, 0, type(uint56).max);
+ _space = bound(_space, 0, type(uint160).max);
+
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_TRANSACTIONS;
+ _payload.calls = new Payload.Call[](2);
+ _payload.calls[0] = Payload.Call({
+ to: _to,
+ value: _value,
+ data: _data,
+ gasLimit: _gasLimit,
+ delegateCall: _delegateCall,
+ onlyFallback: _onlyFallback,
+ behaviorOnError: bound(_behaviorOnError, 0, 0x02)
+ });
+ _payload.calls[1] = Payload.Call({
+ to: address(this),
+ value: 0,
+ data: hex"001122",
+ gasLimit: 1000000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_IGNORE_ERROR
+ });
+ _payload.space = _space;
+ _payload.nonce = _nonce;
+ _payload.parentWallets = _parents;
+
+ bytes32 contractHash = payloadImp.hash(_payload);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, address(payloadImp), uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hashFor_kindTransactions(
+ address _to,
+ uint256 _value,
+ bytes memory _data,
+ uint256 _gasLimit,
+ bool _delegateCall,
+ bool _onlyFallback,
+ uint256 _behaviorOnError,
+ uint256 _space,
+ uint256 _nonce,
+ address[] memory _parents,
+ address _wallet
+ ) external {
+ // Convert nonce into legal range
+ _nonce = bound(_nonce, 0, type(uint56).max);
+ _space = bound(_space, 0, type(uint160).max);
+
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_TRANSACTIONS;
+ _payload.calls = new Payload.Call[](2);
+ _payload.calls[0] = Payload.Call({
+ to: _to,
+ value: _value,
+ data: _data,
+ gasLimit: _gasLimit,
+ delegateCall: _delegateCall,
+ onlyFallback: _onlyFallback,
+ behaviorOnError: bound(_behaviorOnError, 0, 0x02)
+ });
+ _payload.calls[1] = Payload.Call({
+ to: address(this),
+ value: 0,
+ data: hex"001122",
+ gasLimit: 1000000,
+ delegateCall: false,
+ onlyFallback: false,
+ behaviorOnError: Payload.BEHAVIOR_IGNORE_ERROR
+ });
+
+ _payload.space = _space;
+ _payload.nonce = _nonce;
+ _payload.parentWallets = _parents;
+
+ bytes32 contractHash = Payload.hashFor(_payload, _wallet);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, _wallet, uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hashFor_kindTransactions(
+ Payload.Call[] memory _calls,
+ uint256 _space,
+ uint256 _nonce,
+ address[] memory _parents,
+ address _wallet
+ ) external {
+ // Convert nonce into legal range
+ _nonce = bound(_nonce, 0, type(uint56).max);
+ _space = bound(_space, 0, type(uint160).max);
+
+ Payload.Decoded memory _payload;
+ _payload.kind = Payload.KIND_TRANSACTIONS;
+ _payload.calls = _calls;
+
+ _payload.space = _space;
+ _payload.nonce = _nonce;
+ _payload.parentWallets = _parents;
+
+ boundToLegalPayload(_payload);
+
+ bytes32 contractHash = Payload.hashFor(_payload, _wallet);
+ bytes32 payloadHash = PrimitivesRPC.hashForPayload(vm, _wallet, uint64(block.chainid), _payload);
+ assertEq(contractHash, payloadHash);
+ }
+
+ function test_hashFor_invalidPayload(
+ uint8 _kind
+ ) external {
+ _kind = uint8(bound(_kind, 0x04, 0xff));
+ Payload.Decoded memory _payload;
+ _payload.kind = _kind;
+
+ vm.expectRevert(abi.encodeWithSelector(Payload.InvalidKind.selector, _kind));
+ payloadImp.toEIP712(_payload);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/utils/Base64.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/Base64.t.sol
new file mode 100644
index 000000000..73539d3ee
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/Base64.t.sol
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Base64 } from "../../src/utils/Base64.sol";
+import { Test, Vm } from "forge-std/Test.sol";
+
+contract Base64Test is Test {
+
+ function test_encode(
+ bytes calldata data
+ ) external pure {
+ // Test standard encoding
+ string memory result = Base64.encode(data);
+ string memory expected = vm.toBase64(data);
+ assertEq(result, expected);
+
+ // Test file-safe encoding
+ string memory fileSafeResult = Base64.encode(data, true);
+ string memory fileSafeExpected = vm.toBase64URL(data);
+ assertEq(fileSafeResult, fileSafeExpected);
+
+ // Test encoding without padding
+ string memory noPaddingResult = Base64.encode(data, false, true);
+ string memory noPaddingExpected = removePadding(vm.toBase64(data));
+ assertEq(noPaddingResult, noPaddingExpected);
+
+ // Test file-safe encoding without padding
+ string memory fileSafeNoPaddingResult = Base64.encode(data, true, true);
+ string memory fileSafeNoPaddingExpected = removePadding(vm.toBase64URL(data));
+ assertEq(fileSafeNoPaddingResult, fileSafeNoPaddingExpected);
+ }
+
+ function test_decode(
+ bytes calldata data
+ ) external pure {
+ // Test standard base64
+ string memory encoded = Base64.encode(data);
+ bytes memory decoded = Base64.decode(encoded);
+ assertEq(decoded, data);
+
+ // Test file-safe base64
+ string memory fileSafeEncoded = Base64.encode(data, true);
+ bytes memory fileSafeDecoded = Base64.decode(fileSafeEncoded);
+ assertEq(fileSafeDecoded, data);
+
+ // Test without padding
+ string memory noPaddingEncoded = Base64.encode(data, false, true);
+ bytes memory noPaddingDecoded = Base64.decode(noPaddingEncoded);
+ assertEq(noPaddingDecoded, data);
+
+ // Test file-safe without padding
+ string memory fileSafeNoPaddingEncoded = Base64.encode(data, true, true);
+ bytes memory fileSafeNoPaddingDecoded = Base64.decode(fileSafeNoPaddingEncoded);
+ assertEq(fileSafeNoPaddingDecoded, data);
+ }
+
+ function test_encode_empty() external pure {
+ bytes memory empty;
+ string memory result = Base64.encode(empty);
+ assertEq(result, "");
+ }
+
+ function test_decode_empty() external pure {
+ string memory empty = "";
+ bytes memory result = Base64.decode(empty);
+ assertEq(result.length, 0);
+ }
+
+ // Manual test cases for specific scenarios
+ function test_manual_cases() external pure {
+ // Test single byte
+ bytes memory singleByte = hex"01";
+ string memory encoded = Base64.encode(singleByte);
+ assertEq(encoded, "AQ==");
+ bytes memory decoded = Base64.decode(encoded);
+ assertEq(decoded, singleByte);
+
+ // Test two bytes
+ bytes memory twoBytes = hex"0102";
+ encoded = Base64.encode(twoBytes);
+ assertEq(encoded, "AQI=");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, twoBytes);
+
+ // Test three bytes
+ bytes memory threeBytes = hex"010203";
+ encoded = Base64.encode(threeBytes);
+ assertEq(encoded, "AQID");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, threeBytes);
+
+ // Test four bytes
+ bytes memory fourBytes = hex"01020304";
+ encoded = Base64.encode(fourBytes);
+ assertEq(encoded, "AQIDBA==");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, fourBytes);
+
+ // Test file-safe encoding
+ encoded = Base64.encode(fourBytes, true);
+ assertEq(encoded, "AQIDBA==");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, fourBytes);
+
+ // Test without padding
+ encoded = Base64.encode(fourBytes, false, true);
+ assertEq(encoded, "AQIDBA");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, fourBytes);
+
+ // Test file-safe without padding
+ encoded = Base64.encode(fourBytes, true, true);
+ assertEq(encoded, "AQIDBA");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, fourBytes);
+
+ // Test all zeros
+ bytes memory allZeros = hex"00000000";
+ encoded = Base64.encode(allZeros);
+ assertEq(encoded, "AAAAAA==");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, allZeros);
+
+ // Test all ones
+ bytes memory allOnes = hex"FFFFFFFF";
+ encoded = Base64.encode(allOnes);
+ assertEq(encoded, "/////w==");
+ decoded = Base64.decode(encoded);
+ assertEq(decoded, allOnes);
+
+ // Test non-padded base64 string with length not divisible by 4
+ // This will hit the break statement in the decode function
+ bytes memory nonPaddedData = hex"010203";
+ string memory nonPaddedEncoded = "AQID";
+ bytes memory nonPaddedDecoded = Base64.decode(nonPaddedEncoded);
+ assertEq(nonPaddedDecoded, nonPaddedData);
+
+ // "AQI" is 3 characters (mod 4 = 3), so it goes down the "non-padded" path in decode
+ string memory nonPadded = "AQI";
+ bytes memory expected = hex"0102"; // This is what "AQI=" would normally decode to
+ decoded = Base64.decode(nonPadded);
+ assertEq(decoded, expected);
+ }
+
+ // Helper function to remove padding from base64 string
+ function removePadding(
+ string memory data
+ ) internal pure returns (string memory) {
+ bytes memory dataBytes = bytes(data);
+ uint256 length = dataBytes.length;
+ while (length > 0 && dataBytes[length - 1] == "=") {
+ length--;
+ }
+ bytes memory result = new bytes(length);
+ for (uint256 i = 0; i < length; i++) {
+ result[i] = dataBytes[i];
+ }
+ return string(result);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/utils/LibBytes.t.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/LibBytes.t.sol
new file mode 100644
index 000000000..900dca5dc
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/LibBytes.t.sol
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { LibBytes } from "../../src/utils/LibBytes.sol";
+import { AdvTest } from "./TestUtils.sol";
+import { Test, Vm } from "forge-std/Test.sol";
+
+contract LibBytesImp {
+
+ function readFirstUint8(
+ bytes calldata data
+ ) external pure returns (uint8 a, uint256 newPointer) {
+ return LibBytes.readFirstUint8(data);
+ }
+
+ function readUint8(bytes calldata data, uint256 index) external pure returns (uint8 a, uint256 newPointer) {
+ return LibBytes.readUint8(data, index);
+ }
+
+ function readAddress(bytes calldata data, uint256 index) external pure returns (address a, uint256 newPointer) {
+ return LibBytes.readAddress(data, index);
+ }
+
+ function readUint16(bytes calldata data, uint256 index) external pure returns (uint16 a, uint256 newPointer) {
+ return LibBytes.readUint16(data, index);
+ }
+
+ function readUintX(
+ bytes calldata data,
+ uint256 index,
+ uint256 length
+ ) external pure returns (uint256 a, uint256 newPointer) {
+ return LibBytes.readUintX(data, index, length);
+ }
+
+ function readUint24(bytes calldata data, uint256 index) external pure returns (uint24 a, uint256 newPointer) {
+ return LibBytes.readUint24(data, index);
+ }
+
+ function readUint64(bytes calldata data, uint256 index) external pure returns (uint64 a, uint256 newPointer) {
+ return LibBytes.readUint64(data, index);
+ }
+
+ function readBytes4(bytes calldata data, uint256 pointer) external pure returns (bytes4 a, uint256 newPointer) {
+ return LibBytes.readBytes4(data, pointer);
+ }
+
+ function readBytes32(bytes calldata data, uint256 pointer) external pure returns (bytes32 a, uint256 newPointer) {
+ return LibBytes.readBytes32(data, pointer);
+ }
+
+ function readUint256(bytes calldata data, uint256 index) external pure returns (uint256 a, uint256 newPointer) {
+ return LibBytes.readUint256(data, index);
+ }
+
+ function readUint160(bytes calldata data, uint256 index) external pure returns (uint160 a, uint256 newPointer) {
+ return LibBytes.readUint160(data, index);
+ }
+
+ function readRSVCompact(
+ bytes calldata data,
+ uint256 index
+ ) external pure returns (bytes32 r, bytes32 s, uint8 v, uint256 newPointer) {
+ return LibBytes.readRSVCompact(data, index);
+ }
+
+}
+
+contract LibBytesTest is AdvTest {
+
+ LibBytesImp public bytesImp;
+
+ function setUp() public {
+ bytesImp = new LibBytesImp();
+ }
+
+ function test_readFirstUint8(
+ bytes calldata suffix
+ ) external view {
+ uint8 value = 0x12;
+ bytes memory fullData = bytes.concat(abi.encodePacked(value), suffix);
+ (uint8 result, uint256 newPointer) = bytesImp.readFirstUint8(fullData);
+ assertEq(result, value);
+ assertEq(newPointer, 1);
+ }
+
+ function test_readUint8(bytes calldata prefix, uint8 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (uint8 result, uint256 newPointer) = bytesImp.readUint8(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 1);
+ }
+
+ function test_readAddress(bytes calldata prefix, address value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (address result, uint256 newPointer) = bytesImp.readAddress(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 20);
+ }
+
+ function test_readUint16(bytes calldata prefix, uint16 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (uint16 result, uint256 newPointer) = bytesImp.readUint16(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 2);
+ }
+
+ function test_readUintX(bytes calldata prefix, uint256 value, uint256 length, bytes calldata suffix) external view {
+ length = bound(length, 0, 32);
+
+ uint256 mask = length == 32 ? type(uint256).max : ((1 << (length * 8)) - 1);
+ uint256 maskedValue = value & mask;
+
+ bytes memory encodedValue;
+ if (length == 1) {
+ encodedValue = abi.encodePacked(uint8(maskedValue));
+ } else if (length == 2) {
+ encodedValue = abi.encodePacked(uint16(maskedValue));
+ } else if (length == 3) {
+ encodedValue = abi.encodePacked(uint24(maskedValue));
+ } else if (length == 4) {
+ encodedValue = abi.encodePacked(uint32(maskedValue));
+ } else if (length == 5) {
+ encodedValue = abi.encodePacked(uint40(maskedValue));
+ } else if (length == 6) {
+ encodedValue = abi.encodePacked(uint48(maskedValue));
+ } else if (length == 7) {
+ encodedValue = abi.encodePacked(uint56(maskedValue));
+ } else if (length == 8) {
+ encodedValue = abi.encodePacked(uint64(maskedValue));
+ } else if (length == 9) {
+ encodedValue = abi.encodePacked(uint72(maskedValue));
+ } else if (length == 10) {
+ encodedValue = abi.encodePacked(uint80(maskedValue));
+ } else if (length == 11) {
+ encodedValue = abi.encodePacked(uint88(maskedValue));
+ } else if (length == 12) {
+ encodedValue = abi.encodePacked(uint96(maskedValue));
+ } else if (length == 13) {
+ encodedValue = abi.encodePacked(uint104(maskedValue));
+ } else if (length == 14) {
+ encodedValue = abi.encodePacked(uint112(maskedValue));
+ } else if (length == 15) {
+ encodedValue = abi.encodePacked(uint120(maskedValue));
+ } else if (length == 16) {
+ encodedValue = abi.encodePacked(uint128(maskedValue));
+ } else if (length == 17) {
+ encodedValue = abi.encodePacked(uint136(maskedValue));
+ } else if (length == 18) {
+ encodedValue = abi.encodePacked(uint144(maskedValue));
+ } else if (length == 19) {
+ encodedValue = abi.encodePacked(uint152(maskedValue));
+ } else if (length == 20) {
+ encodedValue = abi.encodePacked(uint160(maskedValue));
+ } else if (length == 21) {
+ encodedValue = abi.encodePacked(uint168(maskedValue));
+ } else if (length == 22) {
+ encodedValue = abi.encodePacked(uint176(maskedValue));
+ } else if (length == 23) {
+ encodedValue = abi.encodePacked(uint184(maskedValue));
+ } else if (length == 24) {
+ encodedValue = abi.encodePacked(uint192(maskedValue));
+ } else if (length == 25) {
+ encodedValue = abi.encodePacked(uint200(maskedValue));
+ } else if (length == 26) {
+ encodedValue = abi.encodePacked(uint208(maskedValue));
+ } else if (length == 27) {
+ encodedValue = abi.encodePacked(uint216(maskedValue));
+ } else if (length == 28) {
+ encodedValue = abi.encodePacked(uint224(maskedValue));
+ } else if (length == 29) {
+ encodedValue = abi.encodePacked(uint232(maskedValue));
+ } else if (length == 30) {
+ encodedValue = abi.encodePacked(uint240(maskedValue));
+ } else if (length == 31) {
+ encodedValue = abi.encodePacked(uint248(maskedValue));
+ } else {
+ encodedValue = abi.encodePacked(uint256(maskedValue));
+ }
+
+ bytes memory fullData = bytes.concat(prefix, encodedValue, suffix);
+ uint256 index = prefix.length;
+ (uint256 result, uint256 newPointer) = bytesImp.readUintX(fullData, index, length);
+
+ assertEq(result, maskedValue);
+ assertEq(newPointer, index + length);
+ }
+
+ function test_readUint24(bytes calldata prefix, uint24 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (uint24 result, uint256 newPointer) = bytesImp.readUint24(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 3);
+ }
+
+ function test_readUint64(bytes calldata prefix, uint64 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (uint64 result, uint256 newPointer) = bytesImp.readUint64(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 8);
+ }
+
+ function test_readBytes4(bytes calldata prefix, bytes4 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 pointer = prefix.length;
+ (bytes4 result, uint256 newPointer) = bytesImp.readBytes4(fullData, pointer);
+ assertEq(result, value);
+ assertEq(newPointer, pointer + 4);
+ }
+
+ function test_readBytes32(bytes calldata prefix, bytes32 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 pointer = prefix.length;
+ (bytes32 result, uint256 newPointer) = bytesImp.readBytes32(fullData, pointer);
+ assertEq(result, value);
+ assertEq(newPointer, pointer + 32);
+ }
+
+ function test_readUint256(bytes calldata prefix, uint256 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (uint256 result, uint256 newPointer) = bytesImp.readUint256(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 32);
+ }
+
+ function test_readUint160(bytes calldata prefix, uint160 value, bytes calldata suffix) external view {
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(value), suffix);
+ uint256 index = prefix.length;
+ (uint160 result, uint256 newPointer) = bytesImp.readUint160(fullData, index);
+ assertEq(result, value);
+ assertEq(newPointer, index + 20);
+ }
+
+ function test_readRSVCompact(
+ bytes calldata prefix,
+ bytes32 r,
+ uint256 sWithParity,
+ bytes calldata suffix
+ ) external view {
+ bool parityBit = (sWithParity & (1 << 255)) > 0;
+ bytes32 s = bytes32(sWithParity & ((1 << 255) - 1));
+ uint8 expectedV = parityBit ? 28 : 27;
+
+ bytes memory fullData = bytes.concat(prefix, abi.encodePacked(r), abi.encodePacked(bytes32(sWithParity)), suffix);
+ uint256 index = prefix.length;
+ (bytes32 resultR, bytes32 resultS, uint8 resultV, uint256 newPointer) = bytesImp.readRSVCompact(fullData, index);
+
+ assertEq(resultR, r);
+ assertEq(resultS, s);
+ assertEq(resultV, expectedV);
+ assertEq(newPointer, index + 64);
+ }
+
+ function test_readFirstUint8_emptyData() external view {
+ bytes memory emptyData = new bytes(0);
+ bytesImp.readFirstUint8(emptyData);
+ }
+
+ function test_readUint8_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length > 0);
+ bytesImp.readUint8(data, data.length);
+ }
+
+ function test_readAddress_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 20);
+ bytesImp.readAddress(data, 0);
+ }
+
+ function test_readUint16_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 2);
+ bytesImp.readUint16(data, 0);
+ }
+
+ function test_readUint24_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 3);
+ bytesImp.readUint24(data, 0);
+ }
+
+ function test_readUint64_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 8);
+ bytesImp.readUint64(data, 0);
+ }
+
+ function test_readBytes4_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 4);
+ bytesImp.readBytes4(data, 0);
+ }
+
+ function test_readBytes32_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 32);
+ bytesImp.readBytes32(data, 0);
+ }
+
+ function test_readUint256_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 32);
+ bytesImp.readUint256(data, 0);
+ }
+
+ function test_readUint160_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 20);
+ bytesImp.readUint160(data, 0);
+ }
+
+ function test_readRSVCompact_outOfBounds(
+ bytes calldata data
+ ) external view {
+ vm.assume(data.length < 64);
+ bytesImp.readRSVCompact(data, 0);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/utils/PrimitivesRPC.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/PrimitivesRPC.sol
new file mode 100644
index 000000000..d20f8208d
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/PrimitivesRPC.sol
@@ -0,0 +1,581 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { Vm } from "forge-std/Vm.sol";
+import { Payload } from "src/modules/Payload.sol";
+
+library PrimitivesRPC {
+
+ uint256 private constant COUNTER_UNINITIALIZED = 0;
+ uint256 private constant COUNTER_SLOT = uint256(keccak256("sequence.primitives-rpc.counter"));
+
+ function getCounter() private view returns (uint256) {
+ bytes32 counterSlot = bytes32(COUNTER_SLOT);
+ uint256 value;
+ assembly {
+ value := sload(counterSlot)
+ }
+ return value;
+ }
+
+ function setCounter(
+ uint256 value
+ ) private {
+ bytes32 counterSlot = bytes32(COUNTER_SLOT);
+ assembly {
+ sstore(counterSlot, value)
+ }
+ }
+
+ function rpcURL(
+ Vm _vm
+ ) internal returns (string memory) {
+ uint256 minPort = uint256(_vm.envUint("SEQ_SDK_RPC_MIN_PORT"));
+ uint256 maxPort = uint256(_vm.envUint("SEQ_SDK_RPC_MAX_PORT"));
+ require(maxPort >= minPort, "Invalid port range");
+
+ // Get or initialize counter
+ uint256 counter = getCounter();
+ if (counter == COUNTER_UNINITIALIZED) {
+ counter = uint256(keccak256(abi.encodePacked(msg.data)));
+ }
+
+ // Increment counter
+ counter++;
+ setCounter(counter);
+
+ // Generate port within range using counter
+ uint256 range = maxPort - minPort + 1;
+ uint256 randomPort = minPort + (counter % range);
+
+ string memory prefix = _vm.envString("SEQ_SDK_RPC_URL_PREFIX");
+ string memory suffix = _vm.envString("SEQ_SDK_RPC_URL_SUFFIX");
+
+ return string.concat(prefix, _vm.toString(randomPort), suffix);
+ }
+
+ // ----------------------------------------------------------------
+ // devTools
+ // ----------------------------------------------------------------
+
+ function randomConfig(
+ Vm _vm,
+ uint256 _maxDepth,
+ uint256 _seed,
+ uint256 _minThresholdOnNested,
+ string memory _skew
+ ) internal returns (string memory) {
+ string memory params = string.concat(
+ '{"maxDepth":',
+ _vm.toString(_maxDepth),
+ ',"seed":"',
+ _vm.toString(_seed),
+ '","minThresholdOnNested":',
+ _vm.toString(_minThresholdOnNested),
+ ',"skewed":"',
+ _skew,
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "devTools_randomConfig", params);
+ return string(rawResponse);
+ }
+
+ function randomSessionTopology(
+ Vm _vm,
+ uint256 _maxDepth,
+ uint256 _maxPermissions,
+ uint256 _maxRules,
+ uint256 _seed
+ ) internal returns (string memory) {
+ string memory params = string.concat(
+ '{"maxDepth":',
+ _vm.toString(_maxDepth),
+ ',"maxPermissions":',
+ _vm.toString(_maxPermissions),
+ ',"maxRules":',
+ _vm.toString(_maxRules),
+ ',"seed":"',
+ _vm.toString(_seed),
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "devTools_randomSessionTopology", params);
+ return string(rawResponse);
+ }
+
+ // ----------------------------------------------------------------
+ // payload
+ // ----------------------------------------------------------------
+
+ function toPackedPayload(Vm _vm, Payload.Decoded memory _decoded) internal returns (bytes memory) {
+ string memory params = string.concat('{"payload":"', _vm.toString(abi.encode(_decoded)), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "payload_toPacked", params);
+ return (rawResponse);
+ }
+
+ function toPackedPayloadForWallet(
+ Vm _vm,
+ Payload.Decoded memory _decoded,
+ address _wallet
+ ) internal returns (bytes memory) {
+ string memory params =
+ string.concat('{"payload":"', _vm.toString(abi.encode(_decoded)), '","wallet":"', _vm.toString(_wallet), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "payload_toPacked", params);
+ return (rawResponse);
+ }
+
+ function hashForPayload(
+ Vm _vm,
+ address _wallet,
+ uint64 _chainId,
+ Payload.Decoded memory _decoded
+ ) internal returns (bytes32) {
+ string memory params = string.concat(
+ '{"wallet":"',
+ _vm.toString(_wallet),
+ '","chainId":"',
+ _vm.toString(_chainId),
+ '","payload":"',
+ _vm.toString(abi.encode(_decoded)),
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "payload_hashFor", params);
+ return abi.decode(rawResponse, (bytes32));
+ }
+
+ // ----------------------------------------------------------------
+ // config
+ // ----------------------------------------------------------------
+
+ function newConfig(
+ Vm _vm,
+ uint16 _threshold,
+ uint256 _checkpoint,
+ string memory _elements
+ ) internal returns (string memory) {
+ string memory params = string.concat(
+ '{"threshold":"',
+ _vm.toString(_threshold),
+ '","checkpoint":"',
+ _vm.toString(_checkpoint),
+ '","from":"flat","content":"',
+ _elements,
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "config_new", params);
+ return string(rawResponse);
+ }
+
+ function newConfigWithCheckpointer(
+ Vm _vm,
+ address _checkpointer,
+ uint16 _threshold,
+ uint256 _checkpoint,
+ string memory _elements
+ ) internal returns (string memory) {
+ string memory params = string.concat(
+ '{"threshold":"',
+ _vm.toString(_threshold),
+ '","checkpoint":"',
+ _vm.toString(_checkpoint),
+ '","from":"flat","content":"',
+ _elements,
+ '","checkpointer":"',
+ _vm.toString(_checkpointer),
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "config_new", params);
+ return string(rawResponse);
+ }
+
+ function toEncodedConfig(Vm _vm, string memory configJson) internal returns (bytes memory) {
+ string memory params = string.concat('{"input":', configJson, "}");
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "config_encode", params);
+ return (rawResponse);
+ }
+
+ function getImageHash(Vm _vm, string memory configJson) internal returns (bytes32) {
+ string memory params = string.concat('{"input":', configJson, "}");
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "config_imageHash", params);
+ bytes memory hexBytes = (rawResponse);
+ return abi.decode(hexBytes, (bytes32));
+ }
+
+ // ----------------------------------------------------------------
+ // signature
+ // ----------------------------------------------------------------
+
+ function toEncodedSignature(
+ Vm _vm,
+ string memory configJson,
+ string memory signatures,
+ bool _chainId
+ ) internal returns (bytes memory) {
+ // If you wanted no chainId, adapt the JSON, e.g. `"chainId":false`.
+ string memory params = string.concat(
+ '{"input":', configJson, ',"signatures":"', signatures, '","chainId":', _chainId ? "true" : "false", "}"
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "signature_encode", params);
+ return (rawResponse);
+ }
+
+ function toEncodedSignatureWithCheckpointerData(
+ Vm _vm,
+ string memory configJson,
+ string memory signatures,
+ bool _chainId,
+ bytes memory checkpointerData
+ ) internal returns (bytes memory) {
+ string memory params = string.concat(
+ '{"input":',
+ configJson,
+ ',"signatures":"',
+ signatures,
+ '","chainId":',
+ _chainId ? "true" : "false",
+ ',"checkpointerData":"',
+ _vm.toString(checkpointerData),
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "signature_encode", params);
+ return (rawResponse);
+ }
+
+ function concatSignatures(Vm _vm, bytes[] memory _signatures) internal returns (bytes memory) {
+ string memory arrayPrefix = '{"signatures":[';
+ string memory arraySuffix = "]}";
+ string memory arrayMid;
+ for (uint256 i = 0; i < _signatures.length; i++) {
+ arrayMid = string.concat(arrayMid, i == 0 ? '"' : ',"', _vm.toString(_signatures[i]), '"');
+ }
+ string memory params = string.concat(arrayPrefix, arrayMid, arraySuffix);
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "signature_concat", params);
+ return (rawResponse);
+ }
+
+ // ----------------------------------------------------------------
+ // session
+ // ----------------------------------------------------------------
+
+ function sessionEmpty(Vm _vm, address identitySigner) internal returns (string memory) {
+ string memory params = string.concat('{"identitySigner":"', _vm.toString(identitySigner), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_empty", params);
+ return string(rawResponse);
+ }
+
+ function sessionEncodeTopology(Vm _vm, string memory topologyInput) internal returns (bytes memory) {
+ string memory params = string.concat('{"sessionTopology":', topologyInput, "}");
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_encodeTopology", params);
+ return rawResponse;
+ }
+
+ function sessionEncodeCallSignatures(
+ Vm _vm,
+ string memory topologyInput,
+ string[] memory callSignatures,
+ address[] memory explicitSigners,
+ address[] memory implicitSigners
+ ) internal returns (bytes memory) {
+ string memory callSignaturesJson = _toJsonUnwrapped(_vm, callSignatures);
+ string memory explicitSignersJson = _toJson(_vm, explicitSigners);
+ string memory implicitSignersJson = _toJson(_vm, implicitSigners);
+ string memory params = string.concat(
+ '{"sessionTopology":',
+ topologyInput,
+ ',"callSignatures":',
+ callSignaturesJson,
+ ',"explicitSigners":',
+ explicitSignersJson,
+ ',"implicitSigners":',
+ implicitSignersJson,
+ "}"
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_encodeCallSignatures", params);
+ return rawResponse;
+ }
+
+ function sessionImageHash(Vm _vm, string memory sessionTopologyInput) internal returns (bytes32) {
+ string memory params = string.concat('{"sessionTopology":', sessionTopologyInput, "}");
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_imageHash", params);
+ return abi.decode(rawResponse, (bytes32));
+ }
+
+ // ----------------------------------------------------------------
+ // session explicit
+ // ----------------------------------------------------------------
+
+ function sessionExplicitAdd(
+ Vm _vm,
+ string memory sessionInput,
+ string memory topologyInput
+ ) internal returns (string memory) {
+ string memory params = string.concat('{"explicitSession":', sessionInput, ',"sessionTopology":', topologyInput, "}");
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_explicit_add", params);
+ return string(rawResponse);
+ }
+
+ function sessionExplicitRemove(
+ Vm _vm,
+ address explicitSessionAddress,
+ string memory topologyInput
+ ) internal returns (string memory) {
+ string memory params = string.concat(
+ '{"explicitSessionAddress":"', _vm.toString(explicitSessionAddress), '","sessionTopology":', topologyInput, "}"
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_explicit_remove", params);
+ return string(rawResponse);
+ }
+
+ // ----------------------------------------------------------------
+ // session implicit
+ // ----------------------------------------------------------------
+
+ function sessionImplicitAddBlacklistAddress(
+ Vm _vm,
+ string memory topologyInput,
+ address addressToAdd
+ ) internal returns (string memory) {
+ string memory params =
+ string.concat('{"sessionTopology":', topologyInput, ',"blacklistAddress":"', _vm.toString(addressToAdd), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_implicit_addBlacklistAddress", params);
+ return string(rawResponse);
+ }
+
+ function sessionImplicitRemoveBlacklistAddress(
+ Vm _vm,
+ string memory topologyInput,
+ address addressToRemove
+ ) internal returns (string memory) {
+ string memory params =
+ string.concat('{"sessionTopology":', topologyInput, ',"blacklistAddress":"', _vm.toString(addressToRemove), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "session_implicit_removeBlacklistAddress", params);
+ return string(rawResponse);
+ }
+
+ // ----------------------------------------------------------------
+ // wallet
+ // ----------------------------------------------------------------
+
+ function getAddress(Vm _vm, bytes32 _configHash, address _factory, address _module) internal returns (address) {
+ string memory params = string.concat(
+ '{"imageHash":"',
+ _vm.toString(_configHash),
+ '","factory":"',
+ _vm.toString(_factory),
+ '","module":"',
+ _vm.toString(_module),
+ '"}'
+ );
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "address_calculate", params);
+ // Convert the raw response (a non-padded hex string) into an address
+ string memory addrStr = _vm.toString(rawResponse);
+ return parseAddress(addrStr);
+ }
+
+ function parseAddress(
+ string memory _a
+ ) internal pure returns (address) {
+ bytes memory b = bytes(_a);
+ require(b.length == 42, "Invalid address format"); // "0x" + 40 hex characters
+ uint160 addr = 0;
+ for (uint256 i = 2; i < 42; i += 2) {
+ addr *= 256;
+ uint8 b1 = uint8(b[i]);
+ uint8 b2 = uint8(b[i + 1]);
+ uint8 nib1;
+ uint8 nib2;
+ // Convert first hex character
+ if (b1 >= 48 && b1 <= 57) {
+ // '0'-'9'
+ nib1 = b1 - 48;
+ } else if (b1 >= 65 && b1 <= 70) {
+ // 'A'-'F'
+ nib1 = b1 - 55;
+ } else if (b1 >= 97 && b1 <= 102) {
+ // 'a'-'f'
+ nib1 = b1 - 87;
+ } else {
+ revert("Invalid hex char");
+ }
+ // Convert second hex character
+ if (b2 >= 48 && b2 <= 57) {
+ nib2 = b2 - 48;
+ } else if (b2 >= 65 && b2 <= 70) {
+ nib2 = b2 - 55;
+ } else if (b2 >= 97 && b2 <= 102) {
+ nib2 = b2 - 87;
+ } else {
+ revert("Invalid hex char");
+ }
+ addr += uint160(nib1 * 16 + nib2);
+ }
+ return address(addr);
+ }
+
+ // ----------------------------------------------------------------
+ // utils
+ // ----------------------------------------------------------------
+
+ function _toJson(Vm _vm, address[] memory _addresses) internal pure returns (string memory) {
+ if (_addresses.length == 0) {
+ return "[]";
+ }
+ string memory json = '["';
+ for (uint256 i = 0; i < _addresses.length; i++) {
+ json = string.concat(json, _vm.toString(_addresses[i]), '"');
+ if (i < _addresses.length - 1) {
+ json = string.concat(json, ',"');
+ }
+ }
+ return string.concat(json, "]");
+ }
+
+ // For lists of strings
+ function _toJson(Vm, string[] memory _strings) internal pure returns (string memory) {
+ if (_strings.length == 0) {
+ return "[]";
+ }
+ string memory json = '["';
+ for (uint256 i = 0; i < _strings.length; i++) {
+ json = string.concat(json, _strings[i], '"');
+ if (i < _strings.length - 1) {
+ json = string.concat(json, ',"');
+ }
+ }
+ return string.concat(json, "]");
+ }
+
+ // For lists of JSONified strings
+ function _toJsonUnwrapped(Vm, string[] memory _strings) internal pure returns (string memory) {
+ if (_strings.length == 0) {
+ return "[]";
+ }
+ string memory json = "[";
+ for (uint256 i = 0; i < _strings.length; i++) {
+ json = string.concat(json, _strings[i]);
+ if (i < _strings.length - 1) {
+ json = string.concat(json, ",");
+ }
+ }
+ return string.concat(json, "]");
+ }
+
+ // ----------------------------------------------------------------
+ // recovery
+ // ----------------------------------------------------------------
+
+ function recoveryHashFromLeaves(Vm _vm, string memory leaves) internal returns (bytes32) {
+ string memory params = string.concat('{"leaves":"', leaves, '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "recovery_hashFromLeaves", params);
+ return abi.decode(rawResponse, (bytes32));
+ }
+
+ function recoveryEncode(Vm _vm, string memory leaves) internal returns (bytes memory) {
+ string memory params = string.concat('{"leaves":"', leaves, '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "recovery_encode", params);
+ return rawResponse;
+ }
+
+ function recoveryTrim(Vm _vm, string memory leaves, address signer) internal returns (bytes memory) {
+ string memory params = string.concat('{"leaves":"', leaves, '","signer":"', _vm.toString(signer), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "recovery_trim", params);
+ return rawResponse;
+ }
+
+ function recoveryHashEncoded(Vm _vm, bytes memory encoded) internal returns (bytes32) {
+ string memory params = string.concat('{"encoded":"', _vm.toString(encoded), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "recovery_hashEncoded", params);
+ return abi.decode(rawResponse, (bytes32));
+ }
+
+ // ----------------------------------------------------------------
+ // passkeys
+ // ----------------------------------------------------------------
+
+ struct PasskeyPublicKey {
+ bytes32 x;
+ bytes32 y;
+ bool requireUserVerification;
+ string credentialId;
+ bytes32 metadataHash;
+ }
+
+ struct PasskeySignatureComponents {
+ bytes32 r;
+ bytes32 s;
+ bytes authenticatorData;
+ string clientDataJson;
+ }
+
+ function passkeysEncodeSignature(
+ Vm _vm,
+ PasskeyPublicKey memory _pk,
+ PasskeySignatureComponents memory _sig,
+ bool _embedMetadata
+ ) internal returns (bytes memory) {
+ string memory params = '{"x":"';
+ params = string.concat(params, _vm.toString(_pk.x));
+ params = string.concat(params, '","y":"', _vm.toString(_pk.y));
+ params = string.concat(params, '","requireUserVerification":', _pk.requireUserVerification ? "true" : "false");
+ if (bytes(_pk.credentialId).length > 0) {
+ params = string.concat(params, ',"credentialId":"', _pk.credentialId, '"');
+ } else if (_pk.metadataHash != bytes32(0)) {
+ params = string.concat(params, ',"metadataHash":"', _vm.toString(_pk.metadataHash), '"');
+ }
+ params = string.concat(params, ',"r":"', _vm.toString(_sig.r));
+ params = string.concat(params, '","s":"', _vm.toString(_sig.s));
+ params = string.concat(params, '","authenticatorData":"', _vm.toString(_sig.authenticatorData));
+ params = string.concat(params, '","clientDataJson":', _sig.clientDataJson);
+ params = string.concat(params, ',"embedMetadata":', _embedMetadata ? "true" : "false", "}");
+
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "passkeys_encodeSignature", params);
+ return rawResponse;
+ }
+
+ function passkeysDecodeSignature(Vm _vm, bytes memory _encodedSignature) internal returns (string memory) {
+ string memory params = string.concat('{"encodedSignature":"', _vm.toString(_encodedSignature), '"}');
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "passkeys_decodeSignature", params);
+ return string(rawResponse);
+ }
+
+ function passkeysComputeRoot(Vm _vm, PasskeyPublicKey memory _pk) internal returns (bytes32) {
+ string memory params = '{"x":"';
+ params = string.concat(params, _vm.toString(_pk.x));
+ params = string.concat(params, '","y":"', _vm.toString(_pk.y));
+ params = string.concat(params, '","requireUserVerification":', _pk.requireUserVerification ? "true" : "false");
+ if (bytes(_pk.credentialId).length > 0) {
+ params = string.concat(params, ',"credentialId":"', _pk.credentialId, '"');
+ } else if (_pk.metadataHash != bytes32(0)) {
+ params = string.concat(params, ',"metadataHash":"', _vm.toString(_pk.metadataHash), '"');
+ }
+ params = string.concat(params, "}");
+
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "passkeys_computeRoot", params);
+ return abi.decode(rawResponse, (bytes32));
+ }
+
+ function passkeysValidateSignature(
+ Vm _vm,
+ bytes32 _challenge,
+ PasskeyPublicKey memory _pk,
+ PasskeySignatureComponents memory _sig
+ ) internal returns (bool) {
+ string memory params = '{"challenge":"';
+ params = string.concat(params, _vm.toString(_challenge));
+ params = string.concat(params, '","x":"', _vm.toString(_pk.x));
+ params = string.concat(params, '","y":"', _vm.toString(_pk.y));
+ params = string.concat(params, '","requireUserVerification":', _pk.requireUserVerification ? "true" : "false");
+ if (bytes(_pk.credentialId).length > 0) {
+ params = string.concat(params, ',"credentialId":"', _pk.credentialId, '"');
+ } else if (_pk.metadataHash != bytes32(0)) {
+ params = string.concat(params, ',"metadataHash":"', _vm.toString(_pk.metadataHash), '"');
+ }
+ params = string.concat(params, ',"r":"', _vm.toString(_sig.r));
+ params = string.concat(params, '","s":"', _vm.toString(_sig.s));
+ params = string.concat(params, '","authenticatorData":"', _vm.toString(_sig.authenticatorData));
+ params = string.concat(params, '","clientDataJson":', _sig.clientDataJson, "}");
+
+ bytes memory rawResponse = _vm.rpc(rpcURL(_vm), "passkeys_validateSignature", params);
+ return abi.decode(rawResponse, (bool));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/lib/sequence-v3/test/utils/TestUtils.sol b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/TestUtils.sol
new file mode 100644
index 000000000..191a71396
--- /dev/null
+++ b/lib/signals-implicit-mode/lib/sequence-v3/test/utils/TestUtils.sol
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { Payload } from "../../src/modules/Payload.sol";
+import "forge-std/Test.sol";
+import "forge-std/console.sol";
+
+contract AdvTest is Test {
+
+ function boundPk(
+ uint256 _a
+ ) internal pure returns (uint256) {
+ _a = bound(_a, 1, 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364139);
+ return _a;
+ }
+
+ function boundToLegalPayload(
+ Payload.Decoded memory _payload
+ ) internal pure {
+ _payload.kind = uint8(bound(_payload.kind, uint8(0), uint8(Payload.KIND_DIGEST)));
+
+ if (_payload.kind == Payload.KIND_TRANSACTIONS) {
+ _payload.space = bound(_payload.space, 0, type(uint160).max);
+ _payload.nonce = bound(_payload.nonce, 0, type(uint56).max);
+
+ for (uint256 i = 0; i < _payload.calls.length; i++) {
+ _payload.calls[i].behaviorOnError = bound(
+ _payload.calls[i].behaviorOnError,
+ uint256(Payload.BEHAVIOR_IGNORE_ERROR),
+ uint256(Payload.BEHAVIOR_ABORT_ON_ERROR)
+ );
+ }
+ }
+ }
+
+ function assumeNotPrecompile2(
+ address _addr
+ ) internal view {
+ assumeNotPrecompile(_addr);
+ vm.assume(_addr.code.length == 0);
+ vm.assume(_addr != address(0x000000000000000000636F6e736F6c652e6c6f67));
+ vm.assume(_addr != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));
+ }
+
+ function useSeed(
+ uint256 seed
+ ) internal pure returns (bytes32 value, uint256 newSeed) {
+ value = keccak256(abi.encode(seed));
+ newSeed = uint256(value);
+ }
+
+ function boundNoPrecompile(
+ address _addr
+ ) internal view returns (address) {
+ address candidate = _addr;
+ address invalid1 = address(0x000000000000000000636F6e736F6c652e6c6f67);
+ address invalid2 = address(0x4e59b44847b379578588920cA78FbF26c0B4956C);
+
+ while (
+ (uint160(candidate) >= 1 && uint160(candidate) <= 0xff) || candidate == invalid1 || candidate == invalid2
+ || candidate.code.length > 0
+ ) {
+ candidate = address(uint160(uint256(keccak256(abi.encode(candidate)))));
+ }
+
+ return candidate;
+ }
+
+ // ERC-2098 Compact Signature
+ function signRSVCompact(bytes32 hash, Vm.Wallet memory wallet) internal pure returns (bytes memory) {
+ (uint8 v, bytes32 r, bytes32 s) = vm.sign(wallet.privateKey, hash);
+ uint256 yParity = v == 28 ? 1 << 255 : 0;
+ bytes32 yParityAndS = bytes32(uint256(s) | yParity);
+ return abi.encodePacked(r, yParityAndS);
+ }
+
+ function generateRandomString(
+ uint256 seed
+ ) internal pure returns (string memory) {
+ uint256 size;
+
+ (seed, size) = useSeed(seed, 0, 300);
+ bytes memory _bytes = new bytes(size);
+
+ // For every byte, select a UTF-8 random char (a-z, A-Z, 0-9, _, -, !, or ?)
+ for (uint256 i = 0; i < size; i++) {
+ uint256 charType;
+ (seed, charType) = useSeed(seed, 0, 4);
+
+ if (charType == 0) {
+ // lowercase a-z (ASCII 97-122)
+ uint256 char;
+ (seed, char) = useSeed(seed, 97, 122);
+ _bytes[i] = bytes1(uint8(char));
+ } else if (charType == 1) {
+ // uppercase A-Z (ASCII 65-90)
+ uint256 char;
+ (seed, char) = useSeed(seed, 65, 90);
+ _bytes[i] = bytes1(uint8(char));
+ } else if (charType == 2) {
+ // numbers 0-9 (ASCII 48-57)
+ uint256 char;
+ (seed, char) = useSeed(seed, 48, 57);
+ _bytes[i] = bytes1(uint8(char));
+ } else {
+ // special characters: _, -, !, ?
+ uint256 specialChar;
+ (seed, specialChar) = useSeed(seed, 0, 3);
+ if (specialChar == 0) {
+ _bytes[i] = bytes1(uint8(95)); // _ (underscore)
+ } else if (specialChar == 1) {
+ _bytes[i] = bytes1(uint8(45)); // - (hyphen)
+ } else if (specialChar == 2) {
+ _bytes[i] = bytes1(uint8(33)); // ! (exclamation mark)
+ } else {
+ _bytes[i] = bytes1(uint8(63)); // ? (question mark)
+ }
+ }
+ }
+ return string(_bytes);
+ }
+
+ function useSeed(uint256 _seed, uint256 _min, uint256 _max) internal pure returns (uint256 seed, uint256 val) {
+ val = uint256(keccak256(abi.encode(_seed)));
+ seed = val;
+ val = val % (_max - _min + 1) + _min;
+ }
+
+}
diff --git a/lib/signals-implicit-mode/script/Deploy.s.sol b/lib/signals-implicit-mode/script/Deploy.s.sol
new file mode 100644
index 000000000..2505cb9a1
--- /dev/null
+++ b/lib/signals-implicit-mode/script/Deploy.s.sol
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.27;
+
+import { SingletonDeployer, console } from "erc2470-libs/script/SingletonDeployer.s.sol";
+import { ImplicitProjectRegistry } from "src/registry/ImplicitProjectRegistry.sol";
+
+contract Deploy is SingletonDeployer {
+
+ function run() external {
+ uint256 pk = vm.envUint("PRIVATE_KEY");
+
+ bytes32 salt = bytes32(0);
+
+ bytes memory initCode = abi.encodePacked(type(ImplicitProjectRegistry).creationCode);
+ _deployIfNotAlready("ImplicitProjectRegistry", initCode, salt, pk);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/src/helper/SignalsImplicitMode.sol b/lib/signals-implicit-mode/src/helper/SignalsImplicitMode.sol
new file mode 100644
index 000000000..8af9e37c0
--- /dev/null
+++ b/lib/signals-implicit-mode/src/helper/SignalsImplicitMode.sol
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { IImplicitProjectValidation } from "../registry/IImplicitProjectValidation.sol";
+
+import { ERC165, IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol";
+import { Attestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol";
+import { ISignalsImplicitMode } from "sequence-v3/src/extensions/sessions/implicit/ISignalsImplicitMode.sol";
+import { Payload } from "sequence-v3/src/modules/Payload.sol";
+
+/// @title SignalsImplicitMode
+/// @author Michael Standen
+/// @notice Base contract for implicit mode validation by project
+abstract contract SignalsImplicitMode is ISignalsImplicitMode, ERC165 {
+
+ IImplicitProjectValidation internal _validator;
+ bytes32 internal _projectId;
+
+ /// @notice Initialize implicit mode validation
+ /// @param validator The IImplicitProjectValidation address
+ /// @param projectId The project id
+ function _initializeSignalsImplicitMode(address validator, bytes32 projectId) internal {
+ _validator = IImplicitProjectValidation(validator);
+ _projectId = projectId;
+ }
+
+ /// @inheritdoc ISignalsImplicitMode
+ function acceptImplicitRequest(
+ address wallet,
+ Attestation calldata attestation,
+ Payload.Call calldata call
+ ) external view returns (bytes32) {
+ _validateImplicitRequest(wallet, attestation, call);
+ return _validator.validateAttestation(wallet, attestation, _projectId);
+ }
+
+ /// @notice Validates an implicit request
+ /// @dev Optional hook for additional validation of the implicit requests
+ /// @param wallet The wallet's address
+ /// @param attestation The attestation data
+ /// @param call The call to validate
+ function _validateImplicitRequest(
+ address wallet,
+ Attestation calldata attestation,
+ Payload.Call calldata call
+ ) internal view virtual { }
+
+ /// @inheritdoc IERC165
+ function supportsInterface(
+ bytes4 interfaceId
+ ) public view virtual override returns (bool) {
+ return interfaceId == type(ISignalsImplicitMode).interfaceId || super.supportsInterface(interfaceId);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/src/registry/IImplicitProjectRegistry.sol b/lib/signals-implicit-mode/src/registry/IImplicitProjectRegistry.sol
new file mode 100644
index 000000000..aade1463a
--- /dev/null
+++ b/lib/signals-implicit-mode/src/registry/IImplicitProjectRegistry.sol
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { IImplicitProjectValidation } from "./IImplicitProjectValidation.sol";
+
+/// @title IImplicitProjectRegistry
+/// @author Michael Standen
+/// @notice Interface for the registry of projects supporting implicit sessions
+interface IImplicitProjectRegistry is IImplicitProjectValidation {
+
+ /// @notice Claim a project
+ /// @param projectIdUpper The project id upper
+ /// @return projectId The concatenation of the `projectIdUpper` and the `msg.sender`
+ function claimProject(
+ bytes12 projectIdUpper
+ ) external returns (bytes32 projectId);
+
+ /// @notice Transfer a project
+ /// @param projectId The project id
+ /// @param newOwner The new owner
+ function transferProject(bytes32 projectId, address newOwner) external;
+
+ /// @notice Add a project URL
+ /// @param projectId The project id
+ /// @param projectUrl The project URL
+ function addProjectUrl(bytes32 projectId, string memory projectUrl) external;
+
+ /// @notice Remove a project URL
+ /// @param projectId The project id
+ /// @param projectUrl The project URL
+ function removeProjectUrl(bytes32 projectId, string memory projectUrl) external;
+
+ /// @notice List project URLs
+ /// @param projectId The project id
+ /// @return projectUrls The project URLs
+ function listProjectUrls(
+ bytes32 projectId
+ ) external view returns (bytes32[] memory);
+
+ /// @notice Not project owner error
+ error NotProjectOwner();
+
+ /// @notice Project already claimed error
+ error ProjectAlreadyClaimed();
+
+ /// @notice Invalid project owner error
+ error InvalidProjectOwner();
+
+ /// @notice Project URL not found error
+ error ProjectUrlNotFound();
+
+ /// @notice Project URL already exists error
+ error ProjectUrlAlreadyExists();
+
+ /// @notice Invalid project URL index error
+ error InvalidProjectUrlIndex();
+
+ /// @notice Emitted when a project is claimed
+ event ProjectClaimed(bytes32 indexed projectId, address indexed owner);
+
+ /// @notice Emitted when a project owner is transferred
+ event ProjectOwnerTransferred(bytes32 indexed projectId, address indexed newOwner);
+
+ /// @notice Emitted when a project URL is added
+ event ProjectUrlAdded(bytes32 indexed projectId, bytes32 indexed urlHash);
+
+ /// @notice Emitted when a project URL is removed
+ event ProjectUrlRemoved(bytes32 indexed projectId, bytes32 indexed urlHash);
+
+}
diff --git a/lib/signals-implicit-mode/src/registry/IImplicitProjectValidation.sol b/lib/signals-implicit-mode/src/registry/IImplicitProjectValidation.sol
new file mode 100644
index 000000000..b68c4a61e
--- /dev/null
+++ b/lib/signals-implicit-mode/src/registry/IImplicitProjectValidation.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { Attestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol";
+
+/// @title IImplicitProjectValidation
+/// @author Michael Standen
+/// @notice Interface for contracts supporting validation of implicit sessions for projects
+interface IImplicitProjectValidation {
+
+ /// @notice Invalid redirect url error
+ error InvalidRedirectUrl();
+
+ /// @notice Check if a project has a code
+ /// @param wallet The wallet address
+ /// @param attestation The attestation
+ /// @param projectId The project id
+ /// @return magic The attestation magic bytes for the wallet address
+ function validateAttestation(
+ address wallet,
+ Attestation calldata attestation,
+ bytes32 projectId
+ ) external view returns (bytes32);
+
+}
diff --git a/lib/signals-implicit-mode/src/registry/ImplicitProjectRegistry.sol b/lib/signals-implicit-mode/src/registry/ImplicitProjectRegistry.sol
new file mode 100644
index 000000000..eabe23c41
--- /dev/null
+++ b/lib/signals-implicit-mode/src/registry/ImplicitProjectRegistry.sol
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { IImplicitProjectRegistry } from "./IImplicitProjectRegistry.sol";
+import { IImplicitProjectValidation } from "./IImplicitProjectValidation.sol";
+
+import { Attestation, LibAttestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol";
+
+/// @title ImplicitProjectRegistry
+/// @author Michael Standen
+/// @notice Registry of projects supporting implicit sessions
+contract ImplicitProjectRegistry is IImplicitProjectRegistry {
+
+ using LibAttestation for Attestation;
+
+ /// @notice Project owner
+ mapping(bytes32 => address) public projectOwner;
+
+ /// @notice Project URLs
+ mapping(bytes32 => mapping(bytes32 => bool)) public isProjectUrl;
+ mapping(bytes32 => bytes32[]) public projectUrlsList;
+
+ modifier onlyProjectOwner(
+ bytes32 projectId
+ ) {
+ if (projectOwner[projectId] != msg.sender) {
+ revert IImplicitProjectRegistry.NotProjectOwner();
+ }
+ _;
+ }
+
+ /// @inheritdoc IImplicitProjectRegistry
+ function claimProject(
+ bytes12 projectIdUpper
+ ) public returns (bytes32 projectId) {
+ address owner = msg.sender;
+ if (owner == address(0)) {
+ revert IImplicitProjectRegistry.InvalidProjectOwner();
+ }
+ projectId = bytes32(abi.encodePacked(projectIdUpper, owner));
+ if (projectOwner[projectId] != address(0)) {
+ revert IImplicitProjectRegistry.ProjectAlreadyClaimed();
+ }
+ projectOwner[projectId] = owner;
+ emit IImplicitProjectRegistry.ProjectClaimed(projectId, owner);
+
+ return projectId;
+ }
+
+ /// @inheritdoc IImplicitProjectRegistry
+ function transferProject(bytes32 projectId, address newOwner) public onlyProjectOwner(projectId) {
+ if (newOwner == address(0)) {
+ revert IImplicitProjectRegistry.InvalidProjectOwner();
+ }
+ projectOwner[projectId] = newOwner;
+ emit IImplicitProjectRegistry.ProjectOwnerTransferred(projectId, newOwner);
+ }
+
+ function _addProjectUrlHash(bytes32 projectId, bytes32 projectUrlHash) internal {
+ if (isProjectUrl[projectId][projectUrlHash]) {
+ revert IImplicitProjectRegistry.ProjectUrlAlreadyExists();
+ }
+ isProjectUrl[projectId][projectUrlHash] = true;
+ projectUrlsList[projectId].push(projectUrlHash);
+ emit IImplicitProjectRegistry.ProjectUrlAdded(projectId, projectUrlHash);
+ }
+
+ /// @notice Add a project URL hash
+ /// @param projectId The project id
+ /// @param projectUrlHash The project URL hash
+ function addProjectUrlHash(bytes32 projectId, bytes32 projectUrlHash) external onlyProjectOwner(projectId) {
+ _addProjectUrlHash(projectId, projectUrlHash);
+ }
+
+ /// @notice Add a list of project URL hashes
+ /// @param projectId The project id
+ /// @param projectUrlHashes The project URL hashes
+ function addProjectUrlHashBatch(
+ bytes32 projectId,
+ bytes32[] memory projectUrlHashes
+ ) external onlyProjectOwner(projectId) {
+ for (uint256 i; i < projectUrlHashes.length; i++) {
+ _addProjectUrlHash(projectId, projectUrlHashes[i]);
+ }
+ }
+
+ /// @inheritdoc IImplicitProjectRegistry
+ function addProjectUrl(bytes32 projectId, string memory projectUrl) public onlyProjectOwner(projectId) {
+ _addProjectUrlHash(projectId, _hashUrl(projectUrl));
+ }
+
+ /// @notice Add a list of project URLs
+ /// @param projectId The project id
+ /// @param projectUrls The project URLs
+ function addProjectUrlBatch(bytes32 projectId, string[] memory projectUrls) external onlyProjectOwner(projectId) {
+ for (uint256 i; i < projectUrls.length; i++) {
+ _addProjectUrlHash(projectId, _hashUrl(projectUrls[i]));
+ }
+ }
+
+ function _removeProjectUrlHash(bytes32 projectId, bytes32 projectUrlHash, uint256 urlIdx) internal {
+ if (urlIdx >= projectUrlsList[projectId].length || projectUrlsList[projectId][urlIdx] != projectUrlHash) {
+ revert IImplicitProjectRegistry.InvalidProjectUrlIndex();
+ }
+ isProjectUrl[projectId][projectUrlHash] = false;
+ projectUrlsList[projectId][urlIdx] = projectUrlsList[projectId][projectUrlsList[projectId].length - 1];
+ projectUrlsList[projectId].pop();
+ emit IImplicitProjectRegistry.ProjectUrlRemoved(projectId, projectUrlHash);
+ }
+
+ /// @notice Remove a project URL hash
+ /// @param projectId The project id
+ /// @param projectUrlHash The project URL hash
+ /// @param urlIdx The index of the project URL hash to remove
+ function removeProjectUrlHash(
+ bytes32 projectId,
+ bytes32 projectUrlHash,
+ uint256 urlIdx
+ ) external onlyProjectOwner(projectId) {
+ _removeProjectUrlHash(projectId, projectUrlHash, urlIdx);
+ }
+
+ /// @notice Remove a list of project URL hashes
+ /// @param projectId The project id
+ /// @param projectUrlHashes The project URL hashes
+ /// @param urlIdxs The indexes of the project URL hashes to remove
+ /// @dev The urlIdxs must be sorted in descending order
+ function removeProjectUrlHashBatch(
+ bytes32 projectId,
+ bytes32[] memory projectUrlHashes,
+ uint256[] memory urlIdxs
+ ) external onlyProjectOwner(projectId) {
+ if (projectUrlHashes.length != urlIdxs.length) {
+ revert IImplicitProjectRegistry.InvalidProjectUrlIndex();
+ }
+ // Ensure the urlIdxs are sorted descending to prevent issues with reordering during removals
+ for (uint256 i; i < urlIdxs.length - 1; i++) {
+ if (urlIdxs[i] < urlIdxs[i + 1]) {
+ revert IImplicitProjectRegistry.InvalidProjectUrlIndex();
+ }
+ }
+ for (uint256 i; i < projectUrlHashes.length; i++) {
+ _removeProjectUrlHash(projectId, projectUrlHashes[i], urlIdxs[i]);
+ }
+ }
+
+ /// @inheritdoc IImplicitProjectRegistry
+ /// @dev This function is not optimized. Prefer to use removeProjectUrlHash.
+ function removeProjectUrl(bytes32 projectId, string memory projectUrl) external onlyProjectOwner(projectId) {
+ // Find the index of the project URL hash
+ bytes32 projectUrlHash = _hashUrl(projectUrl);
+ for (uint256 i; i < projectUrlsList[projectId].length; i++) {
+ if (projectUrlsList[projectId][i] == projectUrlHash) {
+ _removeProjectUrlHash(projectId, projectUrlHash, i);
+ return;
+ }
+ }
+ revert IImplicitProjectRegistry.ProjectUrlNotFound();
+ }
+
+ /// @inheritdoc IImplicitProjectRegistry
+ function listProjectUrls(
+ bytes32 projectId
+ ) external view returns (bytes32[] memory) {
+ return projectUrlsList[projectId];
+ }
+
+ /// @inheritdoc IImplicitProjectValidation
+ function validateAttestation(
+ address wallet,
+ Attestation calldata attestation,
+ bytes32 projectId
+ ) external view returns (bytes32) {
+ bytes32 hashedUrl = _hashUrl(attestation.authData.redirectUrl);
+
+ if (isProjectUrl[projectId][hashedUrl]) {
+ return attestation.generateImplicitRequestMagic(wallet);
+ }
+
+ revert IImplicitProjectValidation.InvalidRedirectUrl();
+ }
+
+ function _hashUrl(
+ string memory url
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(url));
+ }
+
+}
diff --git a/lib/signals-implicit-mode/test/ImplicitProjectRegistry.t.sol b/lib/signals-implicit-mode/test/ImplicitProjectRegistry.t.sol
new file mode 100644
index 000000000..54173fbd8
--- /dev/null
+++ b/lib/signals-implicit-mode/test/ImplicitProjectRegistry.t.sol
@@ -0,0 +1,710 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { TestHelper } from "./TestHelper.sol";
+import { SignalsImplicitModeMock } from "./mock/SignalsImplicitModeMock.sol";
+import { Test, console } from "forge-std/Test.sol";
+
+import { IImplicitProjectRegistry } from "../src/registry/IImplicitProjectRegistry.sol";
+import { IImplicitProjectValidation } from "../src/registry/IImplicitProjectValidation.sol";
+import { ImplicitProjectRegistry } from "../src/registry/ImplicitProjectRegistry.sol";
+
+import { Attestation, LibAttestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol";
+
+contract ImplicitProjectRegistryTest is Test, TestHelper {
+
+ using LibAttestation for Attestation;
+
+ ImplicitProjectRegistry public registry;
+
+ function setUp() public {
+ registry = new ImplicitProjectRegistry();
+ }
+
+ // Positive Tests
+
+ function test_claimProject(address owner, bytes12 projectIdUpper) public {
+ vm.assume(owner != address(0));
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectClaimed(projectId, owner);
+
+ vm.prank(owner);
+ bytes32 claimedProjectId = registry.claimProject(projectIdUpper);
+
+ assertEq(claimedProjectId, projectId);
+ assertEq(registry.projectOwner(projectId), owner);
+ }
+
+ function test_transferProject(address owner, address newOwner, bytes12 projectIdUpper, bytes32 urlHash) public {
+ vm.assume(owner != address(0));
+ vm.assume(newOwner != address(0));
+ vm.assume(owner != newOwner);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectOwnerTransferred(projectId, newOwner);
+
+ vm.prank(owner);
+ registry.transferProject(projectId, newOwner);
+
+ assertEq(registry.projectOwner(projectId), newOwner);
+
+ // Check functions now work with the new owner
+ vm.prank(newOwner);
+ registry.addProjectUrlHash(projectId, urlHash);
+ assertEq(registry.listProjectUrls(projectId).length, 1);
+ }
+
+ function test_addProjectUrl(address owner, bytes12 projectIdUpper, string memory url) public {
+ vm.assume(owner != address(0));
+ vm.assume(bytes(url).length > 0);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlAdded(projectId, _hashUrl(url));
+
+ vm.prank(owner);
+ registry.addProjectUrl(projectId, url);
+
+ bytes32[] memory urls = registry.listProjectUrls(projectId);
+ urls = _deduplicateBytes32Array(urls);
+ assertEq(urls[0], _hashUrl(url));
+ }
+
+ function test_addProjectUrlBatch(address owner, bytes12 projectIdUpper, string[] memory urls) public {
+ vm.assume(owner != address(0));
+ vm.assume(urls.length > 0);
+ // Max 10 urls
+ if (urls.length > 10) {
+ assembly {
+ mstore(urls, 10)
+ }
+ }
+ urls = _deduplicateStringArray(urls);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+
+ for (uint256 i; i < urls.length; i++) {
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlAdded(projectId, _hashUrl(urls[i]));
+ }
+
+ registry.addProjectUrlBatch(projectId, urls);
+ vm.stopPrank();
+
+ bytes32[] memory actualUrls = registry.listProjectUrls(projectId);
+ assertEq(actualUrls.length, urls.length);
+ for (uint256 i; i < actualUrls.length; i++) {
+ assertEq(actualUrls[i], _hashUrl(urls[i]));
+ }
+ }
+
+ function test_addProjectUrlHash(address owner, bytes12 projectIdUpper, bytes32 urlHash) public {
+ vm.assume(owner != address(0));
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlAdded(projectId, urlHash);
+
+ vm.prank(owner);
+ registry.addProjectUrlHash(projectId, urlHash);
+
+ bytes32[] memory urls = registry.listProjectUrls(projectId);
+ assertEq(urls[0], urlHash);
+ }
+
+ function test_addProjectUrlHashBatch(address owner, bytes12 projectIdUpper, bytes32[] memory urlHashes) public {
+ vm.assume(owner != address(0));
+ vm.assume(urlHashes.length > 0);
+ // Max 10 urls
+ if (urlHashes.length > 10) {
+ assembly {
+ mstore(urlHashes, 10)
+ }
+ }
+ urlHashes = _deduplicateBytes32Array(urlHashes);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+
+ for (uint256 i; i < urlHashes.length; i++) {
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlAdded(projectId, urlHashes[i]);
+ }
+
+ registry.addProjectUrlHashBatch(projectId, urlHashes);
+ vm.stopPrank();
+
+ bytes32[] memory urls = registry.listProjectUrls(projectId);
+ assertEq(urls.length, urlHashes.length);
+ for (uint256 i; i < urls.length; i++) {
+ assertEq(urls[i], urlHashes[i]);
+ }
+ }
+
+ function test_removeProjectUrl(address owner, bytes12 projectIdUpper, string[] memory urls, uint256 urlIdx) public {
+ vm.assume(owner != address(0));
+ vm.assume(urls.length > 0);
+ // Max 10 urls
+ if (urls.length > 10) {
+ assembly {
+ mstore(urls, 10)
+ }
+ }
+ urls = _deduplicateStringArray(urls);
+ urlIdx = bound(urlIdx, 0, urls.length - 1);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ for (uint256 i; i < urls.length; i++) {
+ registry.addProjectUrl(projectId, urls[i]);
+ }
+
+ bytes32 urlHash = _hashUrl(urls[urlIdx]);
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlRemoved(projectId, urlHash);
+
+ registry.removeProjectUrl(projectId, urls[urlIdx]);
+ vm.stopPrank();
+
+ bytes32[] memory actualUrls = registry.listProjectUrls(projectId);
+ assertEq(actualUrls.length, urls.length - 1);
+ for (uint256 i; i < actualUrls.length; i++) {
+ assertNotEq(actualUrls[i], urlHash);
+ }
+ }
+
+ function test_removeProjectUrlHash(
+ address owner,
+ bytes12 projectIdUpper,
+ bytes32[] memory urlHashes,
+ uint256 urlHashIdx
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(urlHashes.length > 0);
+ // Max 10 urls
+ if (urlHashes.length > 10) {
+ assembly {
+ mstore(urlHashes, 10)
+ }
+ }
+ urlHashes = _deduplicateBytes32Array(urlHashes);
+ urlHashIdx = bound(urlHashIdx, 0, urlHashes.length - 1);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ for (uint256 i; i < urlHashes.length; i++) {
+ registry.addProjectUrlHash(projectId, urlHashes[i]);
+ }
+
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlRemoved(projectId, urlHashes[urlHashIdx]);
+
+ registry.removeProjectUrlHash(projectId, urlHashes[urlHashIdx], urlHashIdx);
+ vm.stopPrank();
+
+ bytes32[] memory urls = registry.listProjectUrls(projectId);
+ assertEq(urls.length, urlHashes.length - 1);
+ for (uint256 i; i < urls.length; i++) {
+ assertNotEq(urls[i], urlHashes[urlHashIdx]);
+ }
+ }
+
+ function test_removeProjectUrlHashBatch(address owner, bytes12 projectIdUpper, bytes32[] memory urlHashes) public {
+ vm.assume(owner != address(0));
+ vm.assume(urlHashes.length > 0);
+ // Max 10 urls
+ if (urlHashes.length > 10) {
+ assembly {
+ mstore(urlHashes, 10)
+ }
+ }
+ urlHashes = _deduplicateBytes32Array(urlHashes);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ registry.addProjectUrlHashBatch(projectId, urlHashes);
+
+ // Reverse the urlHashes list
+ bytes32[] memory reversedUrlHashes = new bytes32[](urlHashes.length);
+ for (uint256 i; i < urlHashes.length; i++) {
+ reversedUrlHashes[i] = urlHashes[urlHashes.length - i - 1];
+ }
+
+ uint256[] memory urlIdxs = new uint256[](urlHashes.length);
+ for (uint256 i; i < urlHashes.length; i++) {
+ urlIdxs[i] = urlHashes.length - i - 1;
+ }
+
+ for (uint256 i; i < urlHashes.length; i++) {
+ vm.expectEmit();
+ emit IImplicitProjectRegistry.ProjectUrlRemoved(projectId, reversedUrlHashes[i]);
+ }
+ registry.removeProjectUrlHashBatch(projectId, reversedUrlHashes, urlIdxs);
+ vm.stopPrank();
+
+ bytes32[] memory urls = registry.listProjectUrls(projectId);
+ assertEq(urls.length, 0);
+ }
+
+ function test_removeProjectUrlHashBatchWithInvalidUrlIdxs(
+ address owner,
+ bytes12 projectIdUpper,
+ bytes32[] memory urlHashes,
+ uint256[] memory urlIdxs
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(urlHashes.length > 0);
+ vm.assume(urlIdxs.length > 0);
+ vm.assume(urlIdxs.length != urlHashes.length);
+
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.InvalidProjectUrlIndex.selector);
+ registry.removeProjectUrlHashBatch(projectId, urlHashes, urlIdxs);
+ vm.stopPrank();
+ }
+
+ function test_removeProjectUrlHashBatchWithInvalidUrlIdxsOrder(
+ address owner,
+ bytes12 projectIdUpper,
+ bytes32[] memory urlHashes,
+ uint256[] memory urlIdxs
+ ) public {
+ vm.assume(owner != address(0));
+ uint256 idxsLength = urlIdxs.length;
+ vm.assume(idxsLength > 1);
+ assembly {
+ mstore(urlHashes, idxsLength)
+ }
+
+ bool isUnsorted = false;
+ for (uint256 i; i < urlIdxs.length - 1; i++) {
+ if (urlIdxs[i] < urlIdxs[i + 1]) {
+ isUnsorted = true;
+ break;
+ }
+ }
+ vm.assume(isUnsorted);
+
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.InvalidProjectUrlIndex.selector);
+ registry.removeProjectUrlHashBatch(projectId, urlHashes, urlIdxs);
+ vm.stopPrank();
+ }
+
+ function test_validateAttestationSingle(
+ address owner,
+ address wallet,
+ bytes12 projectIdUpper,
+ string memory url
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(bytes(url).length > 0);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ Attestation memory attestation;
+ attestation.authData.redirectUrl = url;
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ registry.addProjectUrl(projectId, url);
+ vm.stopPrank();
+
+ bytes32 magic = registry.validateAttestation(wallet, attestation, projectId);
+ assertEq(magic, attestation.generateImplicitRequestMagic(wallet));
+ }
+
+ function test_validateAttestationMultiple(
+ address owner,
+ address wallet,
+ bytes12 projectIdUpper,
+ string[] memory urls,
+ uint256 urlIdx
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(urls.length > 0);
+ // Max 10 urls
+ if (urls.length > 10) {
+ assembly {
+ mstore(urls, 10)
+ }
+ }
+ urls = _deduplicateStringArray(urls);
+ urlIdx = bound(urlIdx, 0, urls.length - 1);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ Attestation memory attestation;
+ attestation.authData.redirectUrl = urls[urlIdx];
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ for (uint256 i; i < urls.length; i++) {
+ registry.addProjectUrl(projectId, urls[i]);
+ }
+ vm.stopPrank();
+
+ bytes32 magic = registry.validateAttestation(wallet, attestation, projectId);
+ assertEq(magic, attestation.generateImplicitRequestMagic(wallet));
+ }
+
+ // Negative Tests
+
+ function test_fail_claimInvalidOwner(
+ bytes12 projectIdUpper
+ ) public {
+ address owner = address(0);
+
+ vm.prank(owner);
+ vm.expectRevert(IImplicitProjectRegistry.InvalidProjectOwner.selector);
+ registry.claimProject(projectIdUpper);
+ }
+
+ function test_fail_transferInvalidOwner(address owner, bytes12 projectIdUpper) public {
+ vm.assume(owner != address(0));
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.prank(owner);
+ vm.expectRevert(IImplicitProjectRegistry.InvalidProjectOwner.selector);
+ registry.transferProject(projectId, address(0));
+ }
+
+ function test_fail_claimProjectTwice(address owner, address otherUser, bytes12 projectIdUpper) public {
+ vm.assume(owner != otherUser);
+ vm.assume(owner != address(0));
+ vm.assume(otherUser != address(0));
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ // Transfer the project to the other user
+ vm.prank(owner);
+ registry.transferProject(projectId, otherUser);
+
+ // Attempt to reclaim
+ vm.expectRevert(IImplicitProjectRegistry.ProjectAlreadyClaimed.selector);
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+ }
+
+ function test_fail_transferByNonAdmin(address owner, address nonOwner, bytes12 projectIdUpper) public {
+ vm.assume(owner != nonOwner);
+ vm.assume(owner != address(0));
+ vm.assume(nonOwner != address(0));
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.transferProject(projectId, nonOwner);
+ }
+
+ function test_fail_addProjectUrlByNonOwner(
+ address owner,
+ address nonOwner,
+ bytes12 projectIdUpper,
+ string memory url
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(owner != nonOwner);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.addProjectUrl(projectId, url);
+ }
+
+ function test_fail_addProjectUrlHashByNonOwner(
+ address owner,
+ address nonOwner,
+ bytes12 projectIdUpper,
+ bytes32 urlHash
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(owner != nonOwner);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.addProjectUrlHash(projectId, urlHash);
+ }
+
+ function test_fail_removeProjectUrlByNonOwner(
+ address owner,
+ address nonOwner,
+ bytes12 projectIdUpper,
+ string memory url
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(owner != nonOwner);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.removeProjectUrl(projectId, url);
+ }
+
+ function test_fail_removeProjectUrlHashByNonOwner(
+ address owner,
+ address nonOwner,
+ bytes12 projectIdUpper,
+ bytes32 urlHash
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(owner != nonOwner);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.removeProjectUrlHash(projectId, urlHash, 0);
+ }
+
+ function test_fail_addProjectUrlHashBatchByNonOwner(
+ address owner,
+ address nonOwner,
+ bytes12 projectIdUpper,
+ bytes32[] memory urlHashes
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(owner != nonOwner);
+ vm.assume(urlHashes.length > 0);
+ // Max 10 urls
+ if (urlHashes.length > 10) {
+ assembly {
+ mstore(urlHashes, 10)
+ }
+ }
+ urlHashes = _deduplicateBytes32Array(urlHashes);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.addProjectUrlHashBatch(projectId, urlHashes);
+ }
+
+ function test_fail_removeProjectUrlHashBatchByNonOwner(
+ address owner,
+ address nonOwner,
+ bytes12 projectIdUpper,
+ bytes32[] memory urlHashes
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(owner != nonOwner);
+ vm.assume(urlHashes.length > 0);
+ // Max 10 urls
+ if (urlHashes.length > 10) {
+ assembly {
+ mstore(urlHashes, 10)
+ }
+ }
+ urlHashes = _deduplicateBytes32Array(urlHashes);
+ uint256[] memory urlIdxs = new uint256[](urlHashes.length);
+ for (uint256 i; i < urlHashes.length; i++) {
+ urlIdxs[i] = i;
+ }
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ for (uint256 i; i < urlHashes.length; i++) {
+ registry.addProjectUrlHash(projectId, urlHashes[i]);
+ }
+ vm.stopPrank();
+
+ vm.expectRevert(IImplicitProjectRegistry.NotProjectOwner.selector);
+ vm.prank(nonOwner);
+ registry.removeProjectUrlHashBatch(projectId, urlHashes, urlIdxs);
+ }
+
+ function test_fail_addProjectUrlAlreadyExists(address owner, bytes12 projectIdUpper, string memory url) public {
+ vm.assume(owner != address(0));
+ vm.assume(bytes(url).length > 0);
+
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+ registry.addProjectUrl(projectId, url);
+
+ vm.expectRevert(IImplicitProjectRegistry.ProjectUrlAlreadyExists.selector);
+ registry.addProjectUrl(projectId, url);
+ vm.stopPrank();
+ }
+
+ function test_fail_addProjectUrlHashAlreadyExists(address owner, bytes12 projectIdUpper, bytes32 urlHash) public {
+ vm.assume(owner != address(0));
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+ registry.addProjectUrlHash(projectId, urlHash);
+
+ vm.expectRevert(IImplicitProjectRegistry.ProjectUrlAlreadyExists.selector);
+ registry.addProjectUrlHash(projectId, urlHash);
+ vm.stopPrank();
+ }
+
+ function test_fail_addProjectUrlAlreadyExistsHash(address owner, bytes12 projectIdUpper, string memory url) public {
+ vm.assume(owner != address(0));
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+ registry.addProjectUrlHash(projectId, _hashUrl(url));
+
+ vm.expectRevert(IImplicitProjectRegistry.ProjectUrlAlreadyExists.selector);
+ registry.addProjectUrl(projectId, url);
+ vm.stopPrank();
+ }
+
+ function test_fail_addProjectUrlHashAlreadyExistsFull(
+ address owner,
+ bytes12 projectIdUpper,
+ string memory url
+ ) public {
+ vm.assume(owner != address(0));
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+ registry.addProjectUrl(projectId, url);
+
+ vm.expectRevert(IImplicitProjectRegistry.ProjectUrlAlreadyExists.selector);
+ registry.addProjectUrlHash(projectId, _hashUrl(url));
+ vm.stopPrank();
+ }
+
+ function test_fail_removeNonexistentUrl(address owner, bytes12 projectIdUpper, string memory url) public {
+ vm.assume(owner != address(0));
+ vm.assume(bytes(url).length > 0);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.ProjectUrlNotFound.selector);
+ vm.prank(owner);
+ registry.removeProjectUrl(projectId, url);
+ }
+
+ function test_fail_removeNonexistentUrlHash(address owner, bytes12 projectIdUpper, bytes32 urlHash) public {
+ vm.assume(owner != address(0));
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ vm.expectRevert(IImplicitProjectRegistry.InvalidProjectUrlIndex.selector);
+ vm.prank(owner);
+ registry.removeProjectUrlHash(projectId, urlHash, 0);
+ }
+
+ function test_fail_removeUrlHashWrongIndex(
+ address owner,
+ bytes12 projectIdUpper,
+ bytes32[] memory urlHashes,
+ uint256 urlHashIdx
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(urlHashes.length > 0);
+ // Max 10 urls
+ if (urlHashes.length > 10) {
+ assembly {
+ mstore(urlHashes, 10)
+ }
+ }
+ urlHashes = _deduplicateBytes32Array(urlHashes);
+ urlHashIdx = bound(urlHashIdx, 0, urlHashes.length - 1);
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.startPrank(owner);
+ registry.claimProject(projectIdUpper);
+ for (uint256 i; i < urlHashes.length; i++) {
+ registry.addProjectUrlHash(projectId, urlHashes[i]);
+ }
+ vm.stopPrank();
+
+ vm.expectRevert(IImplicitProjectRegistry.InvalidProjectUrlIndex.selector);
+ vm.prank(owner);
+ registry.removeProjectUrlHash(projectId, urlHashes[urlHashIdx], urlHashIdx + 1);
+ }
+
+ function test_fail_validateAttestationWithInvalidUrl(
+ address owner,
+ address wallet,
+ bytes12 projectIdUpper,
+ string memory validUrl,
+ string memory invalidUrl
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(bytes(validUrl).length > 0 && bytes(invalidUrl).length > 0);
+ vm.assume(keccak256(bytes(validUrl)) != keccak256(bytes(invalidUrl)));
+
+ bytes32 projectId = _projectId(projectIdUpper, owner);
+
+ vm.prank(owner);
+ registry.claimProject(projectIdUpper);
+
+ Attestation memory attestation;
+ attestation.authData.redirectUrl = invalidUrl;
+
+ vm.prank(owner);
+ registry.addProjectUrl(projectId, validUrl);
+
+ vm.expectRevert(IImplicitProjectValidation.InvalidRedirectUrl.selector);
+ registry.validateAttestation(wallet, attestation, projectId);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/test/SignalsImplicitMode.t.sol b/lib/signals-implicit-mode/test/SignalsImplicitMode.t.sol
new file mode 100644
index 000000000..fba898eb2
--- /dev/null
+++ b/lib/signals-implicit-mode/test/SignalsImplicitMode.t.sol
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { TestHelper } from "./TestHelper.sol";
+import { SignalsImplicitModeMock } from "./mock/SignalsImplicitModeMock.sol";
+import { Test, console } from "forge-std/Test.sol";
+
+import { IImplicitProjectValidation } from "../src/registry/IImplicitProjectValidation.sol";
+import { ImplicitProjectRegistry } from "../src/registry/ImplicitProjectRegistry.sol";
+
+import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol";
+import { Attestation, LibAttestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol";
+import { ISignalsImplicitMode } from "sequence-v3/src/extensions/sessions/implicit/ISignalsImplicitMode.sol";
+import { Payload } from "sequence-v3/src/modules/Payload.sol";
+
+contract SignalsImplicitModeTest is Test, TestHelper {
+
+ using LibAttestation for Attestation;
+
+ SignalsImplicitModeMock public signalsImplicitMode;
+ ImplicitProjectRegistry public registry;
+
+ function setUp() public {
+ registry = new ImplicitProjectRegistry();
+ }
+
+ function test_supportsInterface(
+ bytes32 projectId
+ ) public {
+ signalsImplicitMode = new SignalsImplicitModeMock(address(registry), projectId);
+ assertEq(signalsImplicitMode.supportsInterface(type(IERC165).interfaceId), true);
+ assertEq(signalsImplicitMode.supportsInterface(type(ISignalsImplicitMode).interfaceId), true);
+ }
+
+ function test_acceptsValidUrl(
+ bytes12 projectIdUpper,
+ address owner,
+ string memory url,
+ Attestation memory attestation,
+ address wallet,
+ Payload.Call memory call
+ ) public {
+ vm.assume(owner != address(0));
+ attestation.authData.redirectUrl = url;
+
+ // Claim the project and add the url
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+ registry.addProjectUrl(projectId, url);
+ vm.stopPrank();
+
+ // Initialize the signals implicit mode
+ signalsImplicitMode = new SignalsImplicitModeMock(address(registry), projectId);
+
+ // Accept the implicit request
+ bytes32 expectedMagic = attestation.generateImplicitRequestMagic(wallet);
+ bytes32 actualMagic = signalsImplicitMode.acceptImplicitRequest(wallet, attestation, call);
+ assertEq(actualMagic, expectedMagic);
+ }
+
+ function test_acceptsValidUrlFromMultiple(
+ bytes12 projectIdUpper,
+ address owner,
+ string[] memory urls,
+ uint256 urlIdx,
+ Attestation memory attestation,
+ address wallet,
+ Payload.Call memory call
+ ) public {
+ vm.assume(owner != address(0));
+ vm.assume(urls.length > 0);
+ // Max 10 urls
+ if (urls.length > 10) {
+ assembly {
+ mstore(urls, 10)
+ }
+ }
+ urls = _deduplicateStringArray(urls);
+ urlIdx = bound(urlIdx, 0, urls.length - 1);
+
+ attestation.authData.redirectUrl = urls[urlIdx];
+
+ // Claim the project and add the url
+ vm.startPrank(owner);
+ bytes32 projectId = registry.claimProject(projectIdUpper);
+ for (uint256 i; i < urls.length; i++) {
+ registry.addProjectUrl(projectId, urls[i]);
+ }
+ vm.stopPrank();
+
+ // Initialize the signals implicit mode
+ signalsImplicitMode = new SignalsImplicitModeMock(address(registry), projectId);
+
+ // Accept the implicit request
+ bytes32 expectedMagic = attestation.generateImplicitRequestMagic(wallet);
+ bytes32 actualMagic = signalsImplicitMode.acceptImplicitRequest(wallet, attestation, call);
+ assertEq(actualMagic, expectedMagic);
+ }
+
+ function test_rejectsInvalidUrl(
+ bytes32 projectId,
+ string memory url,
+ Attestation memory attestation,
+ address wallet,
+ Payload.Call memory call
+ ) public {
+ signalsImplicitMode = new SignalsImplicitModeMock(address(registry), projectId);
+ attestation.authData.redirectUrl = url;
+
+ // Accept the implicit request
+ vm.expectRevert(abi.encodeWithSelector(IImplicitProjectValidation.InvalidRedirectUrl.selector));
+ signalsImplicitMode.acceptImplicitRequest(wallet, attestation, call);
+ }
+
+}
diff --git a/lib/signals-implicit-mode/test/TestHelper.sol b/lib/signals-implicit-mode/test/TestHelper.sol
new file mode 100644
index 000000000..64d74c8c4
--- /dev/null
+++ b/lib/signals-implicit-mode/test/TestHelper.sol
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+contract TestHelper {
+
+ function _hashUrl(
+ string memory url
+ ) internal pure returns (bytes32) {
+ return keccak256(abi.encodePacked(url));
+ }
+
+ function _projectId(bytes12 projectIdUpper, address owner) internal pure returns (bytes32 projectId) {
+ projectId = bytes32(abi.encodePacked(projectIdUpper, owner));
+ }
+
+ function _deduplicateBytes32Array(
+ bytes32[] memory array
+ ) internal pure returns (bytes32[] memory deduplicatedArray) {
+ deduplicatedArray = new bytes32[](array.length);
+ uint256 deduplicatedIndex;
+ for (uint256 i; i < array.length; i++) {
+ bool isDuplicate;
+ for (uint256 j; j < deduplicatedIndex; j++) {
+ if (deduplicatedArray[j] == array[i]) {
+ isDuplicate = true;
+ break;
+ }
+ }
+ if (!isDuplicate) {
+ deduplicatedArray[deduplicatedIndex++] = array[i];
+ }
+ }
+ assembly {
+ mstore(deduplicatedArray, deduplicatedIndex)
+ }
+ }
+
+ function _deduplicateStringArray(
+ string[] memory array
+ ) internal pure returns (string[] memory deduplicatedArray) {
+ deduplicatedArray = new string[](array.length);
+ uint256 deduplicatedIndex;
+ for (uint256 i; i < array.length; i++) {
+ bool isDuplicate;
+ bytes32 currentHash = _hashUrl(array[i]);
+ for (uint256 j; j < deduplicatedIndex; j++) {
+ if (currentHash == _hashUrl(deduplicatedArray[j])) {
+ isDuplicate = true;
+ break;
+ }
+ }
+ if (!isDuplicate) {
+ deduplicatedArray[deduplicatedIndex++] = array[i];
+ }
+ }
+ assembly {
+ mstore(deduplicatedArray, deduplicatedIndex)
+ }
+ }
+
+}
diff --git a/lib/signals-implicit-mode/test/mock/SignalsImplicitModeMock.sol b/lib/signals-implicit-mode/test/mock/SignalsImplicitModeMock.sol
new file mode 100644
index 000000000..36bafb9b4
--- /dev/null
+++ b/lib/signals-implicit-mode/test/mock/SignalsImplicitModeMock.sol
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity ^0.8.13;
+
+import { SignalsImplicitMode } from "../../src/helper/SignalsImplicitMode.sol";
+
+contract SignalsImplicitModeMock is SignalsImplicitMode {
+
+ constructor(address registry, bytes32 projectId) {
+ _initializeSignalsImplicitMode(registry, projectId);
+ }
+
+}
diff --git a/package.json b/package.json
index 88b369958..2566e6d6e 100644
--- a/package.json
+++ b/package.json
@@ -1,133 +1,60 @@
{
- "name": "0xsequence",
- "private": true,
+ "name": "sequence-core",
"license": "Apache-2.0",
- "scripts": {
- "build": "pnpm dev && pnpm typecheck && preconstruct build && node scripts/fix-mocha-ref.js",
- "watch": "preconstruct watch",
- "clean": "rimraf ./node_modules",
- "changeset": "changeset",
- "version-packages": "changeset version && pnpm update-version",
- "release": "pnpm build && changeset publish",
- "snapshot": "changeset && changeset version --snapshot && pnpm i && pnpm build && changeset publish --tag snapshot && git tag | grep '0\\.0\\.0' | xargs git tag -d && echo && echo -n 'Published sequence.js snapshot ' && grep '^## ' packages/0xsequence/CHANGELOG.md | head -n 1 | cut -c 4-",
- "update-version": "node ./scripts/update-version",
- "test": "pnpm -r --workspace-concurrency=1 test",
- "test:parallel": "pnpm -r test",
- "lint": "eslint -c .eslintrc.js 'packages/**/src/**/*.{ts,tsx}'",
- "lint:fix": "eslint -c .eslintrc.js --fix 'packages/**/src/**/*.{ts,tsx}'",
- "lint:tests": "eslint -c .eslintrc.js 'packages/**/tests/**/*.{ts,tsx}'",
- "lint:tests:fix": "eslint -c .eslintrc.js --fix 'packages/**/tests/**/*.{ts,tsx}'",
- "format": "prettier --write \"packages/**/src/**/*.ts\" \"packages/**/tests/**/*.ts\"",
- "audit:fix": "pnpm audit --fix",
- "typecheck": "tsc --noEmit",
- "dev": "preconstruct dev",
- "postinstall": "preconstruct dev",
- "coverage": "rimraf ./coverage && rimraf ./.nyc_output && nyc pnpm test",
- "prepare": "husky install"
+ "private": true,
+ "devDependencies": {
+ "@changesets/cli": "^2.29.7",
+ "lefthook": "^1.13.6",
+ "prettier": "^3.6.2",
+ "rimraf": "^6.1.0",
+ "turbo": "^2.6.1",
+ "typescript": "5.8.3"
},
- "husky": {
- "hooks": {
- "pre-commit": "pnpm lint",
- "pre-push": "pnpm lint && pnpm build && pnpm test:parallel"
- }
+ "engines": {
+ "node": ">=18"
},
- "devDependencies": {
- "@0xsequence/abi": "workspace:*",
- "@0xsequence/api": "workspace:*",
- "@0xsequence/auth": "workspace:*",
- "@0xsequence/deployer": "workspace:*",
- "@0xsequence/estimator": "workspace:*",
- "@0xsequence/guard": "workspace:*",
- "@0xsequence/indexer": "workspace:*",
- "@0xsequence/metadata": "workspace:*",
- "@0xsequence/multicall": "workspace:*",
- "@0xsequence/network": "workspace:*",
- "@0xsequence/provider": "workspace:*",
- "@0xsequence/relayer": "workspace:*",
- "@0xsequence/simulator": "workspace:*",
- "@0xsequence/utils": "workspace:*",
- "@0xsequence/wallet": "workspace:*",
- "@babel/core": "^7.21.4",
- "@babel/plugin-transform-class-properties": "^7.23.3",
- "@babel/preset-env": "^7.21.4",
- "@babel/preset-typescript": "^7.21.4",
- "@babel/runtime": "^7.28.4",
- "@changesets/changelog-github": "^0.5.0",
- "@changesets/cli": "^2.26.1",
- "@preconstruct/cli": "^2.8.1",
- "@types/chai": "^4.3.11",
- "@types/chai-as-promised": "^7.1.8",
- "@types/mocha": "^10.0.6",
- "@types/node": "^20.10.4",
- "@typescript-eslint/eslint-plugin": "^6.13.2",
- "@typescript-eslint/parser": "^6.13.2",
- "ava": "^6.0.1",
- "chai": "^4.3.10",
- "chai-as-promised": "^7.1.1",
- "concurrently": "^8.2.2",
- "eslint": "^8.39.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-import": "^2.27.5",
- "eslint-plugin-prettier": "^5.0.1",
- "ethers": "^5.7.2",
- "express": "^4.18.2",
- "hardhat": "^2.22.7",
- "husky": "^8.0.0",
- "mocha": "^10.1.0",
- "nyc": "^15.1.0",
- "prettier": "^3.0.0",
- "puppeteer": "^21.11.0",
- "rimraf": "^5.0.5",
- "ts-node": "^10.9.2",
- "tsx": "^4.6.2",
- "typescript": "~5.3.3",
- "vitest": "^2.0.5",
- "wait-on": "^7.2.0"
+ "dependencies": {
+ "0xsequence": "^2.3.33",
+ "@0xsequence/connect": "0.0.0-20250924112110",
+ "@0xsequence/waas": "^2.3.33",
+ "@0xsequence/wallet": "~2.3.33",
+ "@0xsequence/wallet-contracts": "~3.0.1",
+ "@0xsequence/wallet-primitives": "0.0.0-20250915145821",
+ "@vercel/analytics": "^1.5.0",
+ "ethers": "^6.15.0",
+ "flag": "^5.0.1",
+ "prettier-plugin-solidity": "^2.2.0",
+ "vercel": "^48.10.2"
},
- "resolutions": {},
- "workspaces": [
- "packages/*"
- ],
- "preconstruct": {
- "packages": [
- "packages/*"
- ],
- "globals": {
- "ethers": "ethers"
- }
+ "version": "1.0.0",
+ "description": "**NOTE: please see [v2](https://github.com/0xsequence/sequence.js/tree/v2) branch for sequence.js 2.x.x**",
+ "main": "sequence.js",
+ "directories": {
+ "lib": "lib"
},
- "pnpm": {
- "overrides": {
- "node-forge@<1.0.0": ">=1.0.0",
- "node-forge@<1.3.0": ">=1.3.0",
- "got@<11.8.5": ">=11.8.5",
- "glob-parent@<5.1.2": ">=5.1.2",
- "semver@<5.7.2": ">=5.7.2",
- "webpack-dev-middleware@<=5.3.3": ">=5.3.4",
- "tar@<6.2.1": ">=6.2.1",
- "tough-cookie@<4.1.3": ">=4.1.3",
- "braces@<3.0.3": ">=3.0.3",
- "ws@>=8.0.0 <8.17.1": ">=8.17.1",
- "ws@>=7.0.0 <7.5.10": ">=7.5.10",
- "ws@>=2.1.0 <5.2.4": ">=5.2.4"
- },
- "onlyBuiltDependencies": [
- "bufferutil",
- "es5-ext",
- "esbuild",
- "keccak",
- "puppeteer",
- "secp256k1",
- "utf-8-validate",
- "web3",
- "web3-bzz",
- "web3-shh"
- ]
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/Dargon789/sequence.js.git"
},
- "dependencies": {
- "@tanstack/react-query": "^5.51.21",
- "geth": "^0.4.0",
- "viem": "2.x",
- "wagmi": "0.0.1"
+ "keywords": [],
+ "author": "",
+ "bugs": {
+ "url": "https://github.com/Dargon789/sequence.js/issues"
+ },
+ "homepage": "https://github.com/Dargon789/sequence.js#readme",
+ "scripts": {
+ "build:all": "turbo build",
+ "build:packages": "turbo build --filter=\"./packages/**/*\"",
+ "build": "pnpm build:packages",
+ "dev": "turbo dev",
+ "test": "turbo test --concurrency=1",
+ "lint": "turbo lint",
+ "format": "prettier --list-different --write \"**/*.{ts,tsx,md}\"",
+ "typecheck": "turbo typecheck",
+ "postinstall": "lefthook install",
+ "dev:server": "node packages/wallet/primitives-cli/dist/index.js server",
+ "reinstall": "rimraf -g ./**/node_modules && pnpm install",
+ "test:anvil": "anvil --fork-url https://nodes.sequence.app/arbitrum",
+ "clean": "turbo clean"
}
-}
+}
\ No newline at end of file
diff --git a/packages/multicall/package.json b/packages/multicall/package.json
index 5aa4eadb9..7c695bc12 100644
--- a/packages/multicall/package.json
+++ b/packages/multicall/package.json
@@ -29,7 +29,7 @@
"ethers": "^5.7.2",
"ganache": "^7.5.0",
"json-rpc-engine": "^6.1.0",
- "web3": "^1.8.1",
+ "web3": "^4.16.0",
"web3-provider-engine": "^16.0.4"
},
"files": [
diff --git a/packages/services/api/CHANGELOG.md b/packages/services/api/CHANGELOG.md
index 11007faa9..28bacf399 100644
--- a/packages/services/api/CHANGELOG.md
+++ b/packages/services/api/CHANGELOG.md
@@ -1,41 +1,5 @@
# @0xsequence/api
-## 3.0.0-beta.6
-
-### Patch Changes
-
-- Fix signer 404 error, minor fixes
-
-## 3.0.0-beta.5
-
-### Patch Changes
-
-- Beta release for v3
-
-## 3.0.0-beta.4
-
-### Patch Changes
-
-- RC5 upgrade
-
-## 3.0.0-beta.3
-
-### Patch Changes
-
-- 3.0.0-beta.3 with fixes
-
-## 3.0.0-beta.2
-
-### Patch Changes
-
-- 3.0.0-beta.2 with identity instrument updates
-
-## 3.0.0-beta.1
-
-### Patch Changes
-
-- 3.0.0-beta.1
-
## 2.3.8
### Patch Changes
diff --git a/packages/services/api/package.json b/packages/services/api/package.json
index 6191c7940..bba908e69 100644
--- a/packages/services/api/package.json
+++ b/packages/services/api/package.json
@@ -1,8 +1,8 @@
{
"name": "@0xsequence/api",
- "version": "3.0.0-beta.6",
+ "version": "3.0.0",
"description": "api sub-package for Sequence",
- "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/services/api",
+ "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/api",
"author": "Sequence Platforms Inc.",
"license": "Apache-2.0",
"publishConfig": {
@@ -16,13 +16,13 @@
},
"exports": {
".": {
- "types": "./dist/index.d.ts",
+ "types": "./src/index.ts",
"default": "./dist/index.js"
}
},
"devDependencies": {
"@repo/typescript-config": "workspace:^",
- "@types/node": "^25.0.2",
- "typescript": "^5.9.3"
+ "@types/node": "^22.15.29",
+ "typescript": "^5.8.3"
}
}
diff --git a/packages/services/api/src/api.gen.ts b/packages/services/api/src/api.gen.ts
index bf07aa039..967fad8fe 100644
--- a/packages/services/api/src/api.gen.ts
+++ b/packages/services/api/src/api.gen.ts
@@ -1,506 +1,73 @@
/* eslint-disable */
-// sequence-api v0.4.0 d7026da603b2c29baf21c6aceeebc86eada372d8
+// sequence-api v0.4.0 d43a5aac616814072c69e63f2f81fe65ea10a7e0
// --
-// Code generated by Webrpc-gen@v0.31.0 with typescript generator. DO NOT EDIT.
+// Code generated by webrpc-gen@v0.25.3 with typescript generator. DO NOT EDIT.
//
// webrpc-gen -schema=api.ridl -target=typescript -client -out=./clients/api.gen.ts
-// Webrpc description and code-gen version
-export const WebrpcVersion = 'v1'
-
-// Schema version of your RIDL schema
-export const WebrpcSchemaVersion = 'v0.4.0'
-
-// Schema hash generated from your RIDL schema
-export const WebrpcSchemaHash = 'd7026da603b2c29baf21c6aceeebc86eada372d8'
-
-//
-// Client interface
-//
-
-export interface APIClient {
- /**
- *
- * Runtime
- *
- */
- ping(headers?: object, signal?: AbortSignal): Promise
-
- version(headers?: object, signal?: AbortSignal): Promise
-
- runtimeStatus(headers?: object, signal?: AbortSignal): Promise
-
- clock(headers?: object, signal?: AbortSignal): Promise
-
- getSequenceContext(headers?: object, signal?: AbortSignal): Promise
-
- /**
- *
- * Auth
- *
- * TODO: rename 'ewtString' arg to 'ethauthProof'
- */
- getAuthToken(req: GetAuthTokenRequest, headers?: object, signal?: AbortSignal): Promise
-
- getAuthToken2(req: GetAuthToken2Request, headers?: object, signal?: AbortSignal): Promise
-
- sendPasswordlessLink(
- req: SendPasswordlessLinkRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- registerPublicKey(
- req: RegisterPublicKeyRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- getPublicKey(req: GetPublicKeyRequest, headers?: object, signal?: AbortSignal): Promise
-
- /**
- *
- * Contacts / Friends
- *
- */
- friendList(req: FriendListRequest, headers?: object, signal?: AbortSignal): Promise
-
- getFriendByAddress(
- req: GetFriendByAddressRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- searchFriends(req: SearchFriendsRequest, headers?: object, signal?: AbortSignal): Promise
-
- addFriend(req: AddFriendRequest, headers?: object, signal?: AbortSignal): Promise
-
- updateFriendNickname(
- req: UpdateFriendNicknameRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- removeFriend(req: RemoveFriendRequest, headers?: object, signal?: AbortSignal): Promise
-
- /**
- *
- * Chain-Utils
- *
- */
- contractCall(req: ContractCallRequest, headers?: object, signal?: AbortSignal): Promise
-
- decodeContractCall(
- req: DecodeContractCallRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- lookupContractCallSelectors(
- req: LookupContractCallSelectorsRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- /**
- *
- * User Storage
- *
- */
- userStorageFetch(
- req: UserStorageFetchRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- userStorageSave(req: UserStorageSaveRequest, headers?: object, signal?: AbortSignal): Promise
-
- userStorageDelete(
- req: UserStorageDeleteRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- userStorageFetchAll(
- req: UserStorageFetchAllRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- /**
- *
- * Wallet utils
- *
- */
- getMoonpayLink(req: GetMoonpayLinkRequest, headers?: object, signal?: AbortSignal): Promise
-
- /**
- * - IsUsingGoogleMail(domain: string) => (yes: bool)
- */
- resolveENSAddress(
- req: ResolveENSAddressRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- /**
- * TODO: we can add walletContext optional in the future when we need it
- * NOTE: chainId can be either a number or canonical name
- */
- isValidSignature(
- req: IsValidSignatureRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- isValidMessageSignature(
- req: IsValidMessageSignatureRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- isValidTypedDataSignature(
- req: IsValidTypedDataSignatureRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- isValidETHAuthProof(
- req: IsValidETHAuthProofRequest,
- headers?: object,
- signal?: AbortSignal,
- ): Promise
-
- getOnRampURL(req: GetOnRampURLRequest, headers?: object, signal?: AbortSignal): Promise
-
- transakGetCountries(headers?: object, signal?: AbortSignal): Promise
-
- transakGetCryptoCurrencies(headers?: object, signal?: AbortSignal): Promise
-
- transakGetFiatCurrencies(headers?: object, signal?: AbortSignal): Promise
-
- transakGetPrice(req: TransakGetPriceRequest, headers?: object, signal?: AbortSignal): Promise